/[emacs]/emacs/lisp/textmodes/tex-mode.el
ViewVC logotype

Diff of /emacs/lisp/textmodes/tex-mode.el

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.123.2.1 by miles, Fri Apr 4 06:20:40 2003 UTC revision 1.123.2.2 by miles, Tue Oct 14 23:30:22 2003 UTC
# Line 1  Line 1 
1  ;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands -*- coding: utf-8 -*-  ;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands -*- coding: utf-8 -*-
2    
3  ;; Copyright (C) 1985, 86, 89, 92, 94, 95, 96, 97, 98, 1999, 2002  ;; Copyright (C) 1985,86,89,92,94,95,96,97,98,1999,2002,2003
4  ;;       Free Software Foundation, Inc.  ;;       Free Software Foundation, Inc.
5    
6  ;; Maintainer: FSF  ;; Maintainer: FSF
# Line 196  use." Line 196  use."
196    :group 'tex-view)    :group 'tex-view)
197    
198  ;;;###autoload  ;;;###autoload
199  (defcustom tex-dvi-view-command '(if (eq window-system 'x) \"xdvi\" \"dvi2tty * | cat -s\")  (defcustom tex-dvi-view-command '(if (eq window-system 'x) "xdvi" "dvi2tty * | cat -s")
200    "*Command used by \\[tex-view] to display a `.dvi' file.    "*Command used by \\[tex-view] to display a `.dvi' file.
201  If it is a string, that specifies the command directly.  If it is a string, that specifies the command directly.
202  If this string contains an asterisk (`*'), that is replaced by the file name;  If this string contains an asterisk (`*'), that is replaced by the file name;
# Line 276  Should be a simple file name with no ext Line 276  Should be a simple file name with no ext
276    "File name that \\[tex-print] prints.    "File name that \\[tex-print] prints.
277  Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].")  Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].")
278    
279  (easy-mmode-defsyntax tex-mode-syntax-table  (defvar tex-mode-syntax-table
280    '((?% . "<")    (let ((st (make-syntax-table)))
281      (?\n . ">")      (modify-syntax-entry ?% "<" st)
282      (?\f . ">")      (modify-syntax-entry ?\n ">" st)
283      (?\C-@ . "w")      (modify-syntax-entry ?\f ">" st)
284      (?' . "w")      (modify-syntax-entry ?\C-@ "w" st)
285      (?@ . "_")      (modify-syntax-entry ?' "w" st)
286      (?* . "_")      (modify-syntax-entry ?@ "_" st)
287      (?\t . " ")      (modify-syntax-entry ?* "_" st)
288      (?~ . " ")      (modify-syntax-entry ?\t " " st)
289      (?$ . "$$")      ;; ~ is printed by TeX as a space, but it's semantics in the syntax
290      (?\\ . "/")      ;; of TeX is not `whitespace' (i.e. it's just like \hspace{foo}).
291      (?\" . ".")      (modify-syntax-entry ?~ "." st)
292      (?& . ".")      (modify-syntax-entry ?$ "$$" st)
293      (?_ . ".")      (modify-syntax-entry ?\\ "/" st)
294      (?^ . "."))      (modify-syntax-entry ?\" "." st)
295        (modify-syntax-entry ?& "." st)
296        (modify-syntax-entry ?_ "." st)
297        (modify-syntax-entry ?^ "." st)
298        st)
299    "Syntax table used while in TeX mode.")    "Syntax table used while in TeX mode.")
300    
301  ;;;;  ;;;;
# Line 499  An alternative value is \" . \", if you Line 503  An alternative value is \" . \", if you
503              (bold (regexp-opt '("textbf" "textsc" "textup"              (bold (regexp-opt '("textbf" "textsc" "textup"
504                                  "boldsymbol" "pmb") t))                                  "boldsymbol" "pmb") t))
505              (italic (regexp-opt '("textit" "textsl" "emph") t))              (italic (regexp-opt '("textit" "textsl" "emph") t))
506              (type (regexp-opt '("texttt" "textmd" "textrm" "textsf") t))              ;; FIXME: unimplemented yet.
507                ;; (type (regexp-opt '("texttt" "textmd" "textrm" "textsf") t))
508              ;;              ;;
509              ;; Names of commands whose arg should be fontified as a citation.              ;; Names of commands whose arg should be fontified as a citation.
510              (citations (regexp-opt              (citations (regexp-opt
# Line 690  An alternative value is \" . \", if you Line 695  An alternative value is \" . \", if you
695      (define-key map "\C-c\C-r" 'tex-region)      (define-key map "\C-c\C-r" 'tex-region)
696      (define-key map "\C-c\C-b" 'tex-buffer)      (define-key map "\C-c\C-b" 'tex-buffer)
697      (define-key map "\C-c\C-f" 'tex-file)      (define-key map "\C-c\C-f" 'tex-file)
698        (define-key map "\C-c\C-c" 'tex-compile)
699      (define-key map "\C-c\C-i" 'tex-bibtex-file)      (define-key map "\C-c\C-i" 'tex-bibtex-file)
700      (define-key map "\C-c\C-o" 'latex-insert-block)      (define-key map "\C-c\C-o" 'latex-insert-block)
701      (define-key map "\C-c\C-e" 'latex-close-block)      (define-key map "\C-c\C-e" 'latex-close-block)
# Line 713  An alternative value is \" . \", if you Line 719  An alternative value is \" . \", if you
719  (defvar latex-mode-map  (defvar latex-mode-map
720    (let ((map (make-sparse-keymap)))    (let ((map (make-sparse-keymap)))
721      (set-keymap-parent map tex-mode-map)      (set-keymap-parent map tex-mode-map)
722        (define-key map "\C-c\C-s" 'latex-split-block)
723      map)      map)
724    "Keymap for `latex-mode'.  See also `tex-mode-map'.")    "Keymap for `latex-mode'.  See also `tex-mode-map'.")
725    
# Line 745  Inherits `shell-mode-map' with a few add Line 752  Inherits `shell-mode-map' with a few add
752    
753  ;; This would be a lot simpler if we just used a regexp search,  ;; This would be a lot simpler if we just used a regexp search,
754  ;; but then it would be too slow.  ;; but then it would be too slow.
755  ;;;###autoload  (defun tex-guess-mode ()
 (defun tex-mode ()  
   "Major mode for editing files of input for TeX, LaTeX, or SliTeX.  
 Tries to determine (by looking at the beginning of the file) whether  
 this file is for plain TeX, LaTeX, or SliTeX and calls `plain-tex-mode',  
 `latex-mode', or `slitex-mode', respectively.  If it cannot be determined,  
 such as if there are no commands in the file, the value of `tex-default-mode'  
 says which mode to use."  
   (interactive)  
756    (let ((mode tex-default-mode) slash comment)    (let ((mode tex-default-mode) slash comment)
757      (save-excursion      (save-excursion
758        (goto-char (point-min))        (goto-char (point-min))
# Line 769  says which mode to use." Line 768  says which mode to use."
768                       (concat                       (concat
769                        (regexp-opt '("documentstyle" "documentclass"                        (regexp-opt '("documentstyle" "documentclass"
770                                      "begin" "subsection" "section"                                      "begin" "subsection" "section"
771                                      "part" "chapter" "newcommand") 'words)                                      "part" "chapter" "newcommand"
772                                        "renewcommand") 'words)
773                        "\\|NeedsTeXFormat{LaTeX")))                        "\\|NeedsTeXFormat{LaTeX")))
774                    (if (looking-at                    (if (looking-at
775                         "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}")                         "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}")
# Line 778  says which mode to use." Line 778  says which mode to use."
778                  'plain-tex-mode))))                  'plain-tex-mode))))
779      (funcall mode)))      (funcall mode)))
780    
781    ;; `tex-mode' plays two roles: it's the parent of several sub-modes
782    ;; but it's also the function that chooses between those submodes.
783    ;; To tell the difference between those two cases where the function
784    ;; might be called, we check `delay-mode-hooks'.
785    (define-derived-mode tex-mode text-mode "generic-TeX"
786      (tex-common-initialization))
787    ;; We now move the function and define it again.  This gives a warning
788    ;; in the byte-compiler :-( but it's difficult to avoid because
789    ;; `define-derived-mode' will necessarily define the function once
790    ;; and we need to define it a second time for `autoload' to get the
791    ;; proper docstring.
792    (defalias 'tex-mode-internal (symbol-function 'tex-mode))
793    ;;;###autoload
794    (defun tex-mode ()
795      "Major mode for editing files of input for TeX, LaTeX, or SliTeX.
796    Tries to determine (by looking at the beginning of the file) whether
797    this file is for plain TeX, LaTeX, or SliTeX and calls `plain-tex-mode',
798    `latex-mode', or `slitex-mode', respectively.  If it cannot be determined,
799    such as if there are no commands in the file, the value of `tex-default-mode'
800    says which mode to use."
801      (interactive)
802      (if delay-mode-hooks
803          ;; We're called from one of the children already.
804          (tex-mode-internal)
805        (tex-guess-mode)))
806    
807  ;;;###autoload  ;;;###autoload
808  (defalias 'TeX-mode 'tex-mode)  (defalias 'TeX-mode 'tex-mode)
809  ;;;###autoload  ;;;###autoload
# Line 786  says which mode to use." Line 812  says which mode to use."
812  (defalias 'LaTeX-mode 'latex-mode)  (defalias 'LaTeX-mode 'latex-mode)
813    
814  ;;;###autoload  ;;;###autoload
815  (define-derived-mode plain-tex-mode text-mode "TeX"  (define-derived-mode plain-tex-mode tex-mode "TeX"
816    "Major mode for editing files of input for plain TeX.    "Major mode for editing files of input for plain TeX.
817  Makes $ and } display the characters they match.  Makes $ and } display the characters they match.
818  Makes \" insert `` when it seems to be the beginning of a quotation,  Makes \" insert `` when it seems to be the beginning of a quotation,
# Line 826  tex-show-queue-command Line 852  tex-show-queue-command
852  Entering Plain-tex mode runs the hook `text-mode-hook', then the hook  Entering Plain-tex mode runs the hook `text-mode-hook', then the hook
853  `tex-mode-hook', and finally the hook `plain-tex-mode-hook'.  When the  `tex-mode-hook', and finally the hook `plain-tex-mode-hook'.  When the
854  special subshell is initiated, the hook `tex-shell-hook' is run."  special subshell is initiated, the hook `tex-shell-hook' is run."
855    (tex-common-initialization)    (set (make-local-variable 'tex-command) tex-run-command)
856    (setq tex-command tex-run-command)    (set (make-local-variable 'tex-start-of-header) "%\\*\\*start of header")
857    (setq tex-start-of-header "%\\*\\*start of header")    (set (make-local-variable 'tex-end-of-header) "%\\*\\*end of header")
858    (setq tex-end-of-header "%\\*\\*end of header")    (set (make-local-variable 'tex-trailer) "\\bye\n"))
   (setq tex-trailer "\\bye\n")  
   (run-hooks 'tex-mode-hook))  
859    
860  ;;;###autoload  ;;;###autoload
861  (define-derived-mode latex-mode text-mode "LaTeX"  (define-derived-mode latex-mode tex-mode "LaTeX"
862    "Major mode for editing files of input for LaTeX.    "Major mode for editing files of input for LaTeX.
863  Makes $ and } display the characters they match.  Makes $ and } display the characters they match.
864  Makes \" insert `` when it seems to be the beginning of a quotation,  Makes \" insert `` when it seems to be the beginning of a quotation,
# Line 874  tex-show-queue-command Line 898  tex-show-queue-command
898  Entering Latex mode runs the hook `text-mode-hook', then  Entering Latex mode runs the hook `text-mode-hook', then
899  `tex-mode-hook', and finally `latex-mode-hook'.  When the special  `tex-mode-hook', and finally `latex-mode-hook'.  When the special
900  subshell is initiated, `tex-shell-hook' is run."  subshell is initiated, `tex-shell-hook' is run."
901    (tex-common-initialization)    (set (make-local-variable 'tex-command) latex-run-command)
902    (setq tex-command latex-run-command)    (set (make-local-variable 'tex-start-of-header)
903    (setq tex-start-of-header "\\\\document\\(style\\|class\\)")         "\\\\document\\(style\\|class\\)")
904    (setq tex-end-of-header "\\\\begin\\s-*{document}")    (set (make-local-variable 'tex-end-of-header) "\\\\begin\\s-*{document}")
905    (setq tex-trailer "\\end\\s-*{document}\n")    (set (make-local-variable 'tex-trailer) "\\end\\s-*{document}\n")
906    ;; A line containing just $$ is treated as a paragraph separator.    ;; A line containing just $$ is treated as a paragraph separator.
907    ;; A line starting with $$ starts a paragraph,    ;; A line starting with $$ starts a paragraph,
908    ;; but does not separate paragraphs if it has more stuff on it.    ;; but does not separate paragraphs if it has more stuff on it.
909    (setq paragraph-start    (setq paragraph-start
910          (concat "[\f%]\\|[ \t]*\\($\\|\\$\\$\\|"          (concat "[ \t]*\\(\\$\\$\\|"
911                  "\\\\[][]\\|"                  "\\\\[][]\\|"
912                  "\\\\" (regexp-opt (append                  "\\\\" (regexp-opt (append
913                                      (mapcar 'car latex-section-alist)                                      (mapcar 'car latex-section-alist)
# Line 913  subshell is initiated, `tex-shell-hook' Line 937  subshell is initiated, `tex-shell-hook'
937    (set (make-local-variable 'outline-regexp) latex-outline-regexp)    (set (make-local-variable 'outline-regexp) latex-outline-regexp)
938    (set (make-local-variable 'outline-level) 'latex-outline-level)    (set (make-local-variable 'outline-level) 'latex-outline-level)
939    (set (make-local-variable 'forward-sexp-function) 'latex-forward-sexp)    (set (make-local-variable 'forward-sexp-function) 'latex-forward-sexp)
940    (set (make-local-variable 'skeleton-end-hook) nil)    (set (make-local-variable 'skeleton-end-hook) nil))
   (run-hooks 'tex-mode-hook))  
941    
942  ;;;###autoload  ;;;###autoload
943  (define-derived-mode slitex-mode latex-mode "SliTeX"  (define-derived-mode slitex-mode latex-mode "SliTeX"
# Line 962  Entering SliTeX mode runs the hook `text Line 985  Entering SliTeX mode runs the hook `text
985    (setq tex-start-of-header "\\\\documentstyle{slides}\\|\\\\documentclass{slides}"))    (setq tex-start-of-header "\\\\documentstyle{slides}\\|\\\\documentclass{slides}"))
986    
987  (defun tex-common-initialization ()  (defun tex-common-initialization ()
   (set-syntax-table tex-mode-syntax-table)  
988    ;; Regexp isearch should accept newline and formfeed as whitespace.    ;; Regexp isearch should accept newline and formfeed as whitespace.
989    (set (make-local-variable 'search-whitespace-regexp) "[ \t\r\n\f]+")    (set (make-local-variable 'search-whitespace-regexp) "[ \t\r\n\f]+")
990    ;; A line containing just $$ is treated as a paragraph separator.    ;; A line containing just $$ is treated as a paragraph separator.
# Line 1069  on the line for the invalidity you want Line 1091  on the line for the invalidity you want
1091          (num-matches 0))          (num-matches 0))
1092      (with-output-to-temp-buffer "*Occur*"      (with-output-to-temp-buffer "*Occur*"
1093        (princ "Mismatches:\n")        (princ "Mismatches:\n")
1094        (save-excursion        (with-current-buffer standard-output
         (set-buffer standard-output)  
1095          (occur-mode)          (occur-mode)
1096          ;; This won't actually work...Really, this whole thing should          ;; This won't actually work...Really, this whole thing should
1097          ;; be rewritten instead of being a hack on top of occur.          ;; be rewritten instead of being a hack on top of occur.
# Line 1087  on the line for the invalidity you want Line 1108  on the line for the invalidity you want
1108                    (forward-char 2))                    (forward-char 2))
1109                (goto-char (setq prev-end (point-min))))                (goto-char (setq prev-end (point-min))))
1110              (or (tex-validate-region (point) end)              (or (tex-validate-region (point) end)
1111                  (let* ((oend end)                  (let* ((end (line-beginning-position 2))
                        (end (save-excursion (forward-line 1) (point)))  
1112                         start tem)                         start tem)
1113                    (beginning-of-line)                    (beginning-of-line)
1114                    (setq start (point))                    (setq start (point))
# Line 1194  A prefix arg inhibits the checking." Line 1214  A prefix arg inhibits the checking."
1214    
1215  (defvar latex-block-default "enumerate")  (defvar latex-block-default "enumerate")
1216    
1217    (defvar latex-block-args-alist
1218      '(("array" nil ?\{ (skeleton-read "[options]: ") ?\})
1219        ("tabular" nil ?\{ (skeleton-read "[options]: ") ?\}))
1220      "Skeleton element to use for arguments to particular environments.
1221    Every element of the list has the form (NAME . SKEL-ELEM) where NAME is
1222    the name of the environment and SKEL-ELEM is an element to use in
1223    a skeleton (see `skeleton-insert').")
1224    
1225    (defvar latex-block-body-alist
1226      '(("enumerate" nil '(latex-insert-item) > _)
1227        ("itemize" nil '(latex-insert-item) > _)
1228        ("table" nil "\\caption{" > - "}" > \n _)
1229        ("figure" nil  > _ \n "\\caption{" > _ "}" >))
1230      "Skeleton element to use for the body of particular environments.
1231    Every element of the list has the form (NAME . SKEL-ELEM) where NAME is
1232    the name of the environment and SKEL-ELEM is an element to use in
1233    a skeleton (see `skeleton-insert').")
1234    
1235  ;; Like tex-insert-braces, but for LaTeX.  ;; Like tex-insert-braces, but for LaTeX.
1236  (defalias 'tex-latex-block 'latex-insert-block)  (defalias 'tex-latex-block 'latex-insert-block)
1237  (define-skeleton latex-insert-block  (define-skeleton latex-insert-block
1238    "Create a matching pair of lines \\begin[OPT]{NAME} and \\end{NAME} at point.    "Create a matching pair of lines \\begin{NAME} and \\end{NAME} at point.
1239  Puts point on a blank line between them."  Puts point on a blank line between them."
1240    (let ((choice (completing-read (format "LaTeX block name [%s]: "    (let ((choice (completing-read (format "LaTeX block name [%s]: "
1241                                           latex-block-default)                                           latex-block-default)
# Line 1211  Puts point on a blank line between them. Line 1249  Puts point on a blank line between them.
1249        (push choice latex-block-names))        (push choice latex-block-names))
1250      choice)      choice)
1251    \n "\\begin{" str "}"    \n "\\begin{" str "}"
1252    ?\[ (skeleton-read "[options]: ") & ?\] | -1    (cdr (assoc str latex-block-args-alist))
1253    > \n _ \n    > \n (or (cdr (assoc str latex-block-body-alist)) '(nil > _)) \n
1254    "\\end{" str "}" > \n)    "\\end{" str "}" > \n)
1255    
1256  (define-skeleton latex-insert-item  (define-skeleton latex-insert-item
# Line 1225  Puts point on a blank line between them. Line 1263  Puts point on a blank line between them.
1263  ;;;; LaTeX syntax navigation  ;;;; LaTeX syntax navigation
1264  ;;;;  ;;;;
1265    
1266    (defmacro tex-search-noncomment (&rest body)
1267      "Execute BODY as long as it return non-nil and point is in a comment.
1268    Return the value returned by the last execution of BODY."
1269      (declare (debug t))
1270      (let ((res-sym (make-symbol "result")))
1271        `(let (,res-sym)
1272           (while
1273               (and (setq ,res-sym (progn ,@body))
1274                    (save-excursion (skip-chars-backward "^\n%") (not (bolp)))))
1275           ,res-sym)))
1276    
1277  (defun tex-last-unended-begin ()  (defun tex-last-unended-begin ()
1278    "Leave point at the beginning of the last `\\begin{...}' that is unended."    "Leave point at the beginning of the last `\\begin{...}' that is unended."
1279    (condition-case nil    (condition-case nil
1280        (while (and (re-search-backward "\\\\\\(begin\\|end\\)\\s *{")        (while (and (tex-search-noncomment
1281                       (re-search-backward "\\\\\\(begin\\|end\\)\\s *{"))
1282                    (looking-at "\\\\end"))                    (looking-at "\\\\end"))
1283          (tex-last-unended-begin))          (tex-last-unended-begin))
1284      (search-failed (error "Couldn't find unended \\begin"))))      (search-failed (error "Couldn't find unended \\begin"))))
1285    
1286  (defun tex-next-unmatched-end ()  (defun tex-next-unmatched-end ()
1287    "Leave point at the end of the next `\\end' that is unended."    "Leave point at the end of the next `\\end' that is unended."
1288    (while (and (re-search-forward "\\\\\\(begin\\|end\\)\\s *{[^}]+}")    (while (and (tex-search-noncomment
1289                   (re-search-forward "\\\\\\(begin\\|end\\)\\s *{[^}]+}"))
1290                (save-excursion (goto-char (match-beginning 0))                (save-excursion (goto-char (match-beginning 0))
1291                                (looking-at "\\\\begin")))                                (looking-at "\\\\begin")))
1292      (tex-next-unmatched-end)))      (tex-next-unmatched-end)))
# Line 1507  If NOT-ALL is non-nil, save the `.dvi' f Line 1558  If NOT-ALL is non-nil, save the `.dvi' f
1558    
1559  (add-hook 'kill-emacs-hook 'tex-delete-last-temp-files)  (add-hook 'kill-emacs-hook 'tex-delete-last-temp-files)
1560    
1561    ;;
1562    ;; Machinery to guess the command that the user wants to execute.
1563    ;;
1564    
1565    (defvar tex-compile-history nil)
1566    
1567    (defvar tex-input-files-re
1568      (eval-when-compile
1569        (concat "\\." (regexp-opt '("tex" "texi" "texinfo"
1570                                    "bbl" "ind" "sty" "cls") t)
1571                ;; Include files with no dots (for directories).
1572                "\\'\\|\\`[^.]+\\'")))
1573    
1574    (defcustom tex-use-reftex t
1575      "If non-nil, use RefTeX's list of files to determine what command to use."
1576      :type 'boolean)
1577    
1578    (defvar tex-compile-commands
1579      '(((concat "pdf" tex-command
1580                 " " (if (< 0 (length tex-start-commands))
1581                         (shell-quote-argument tex-start-commands)) " %f")
1582         t "%r.pdf")
1583        ((concat tex-command
1584                 " " (if (< 0 (length tex-start-commands))
1585                         (shell-quote-argument tex-start-commands)) " %f")
1586         t "%r.dvi")
1587        ("xdvi %r &" "%r.dvi")
1588        ("advi %r &" "%r.dvi")
1589        ("bibtex %r" "%r.aux" "%r.bbl")
1590        ("makeindex %r" "%r.idx" "%r.ind")
1591        ("texindex %r.??")
1592        ("dvipdfm %r" "%r.dvi" "%r.pdf")
1593        ("dvipdf %r" "%r.dvi" "%r.pdf")
1594        ("dvips %r" "%r.dvi" "%r.ps")
1595        ("gv %r.ps &" "%r.ps")
1596        ("gv %r.pdf &" "%r.pdf")
1597        ("xpdf %r.pdf &" "%r.pdf")
1598        ("lpr %r.ps" "%r.ps"))
1599      "List of commands for `tex-compile'.
1600    Each element should be of the form (FORMAT IN OUT) where
1601    FORMAT is an expression that evaluates to a string that can contain
1602      - `%r' the main file name without extension.
1603      - `%f' the main file name.
1604    IN can be either a string (with the same % escapes in it) indicating
1605      the name of the input file, or t to indicate that the input is all
1606      the TeX files of the document, or nil if we don't know.
1607    OUT describes the output file and is either a %-escaped string
1608      or nil to indicate that there is no output file.")
1609    
1610    ;; defsubst* gives better byte-code than defsubst.
1611    (defsubst* tex-string-prefix-p (str1 str2)
1612      "Return non-nil if STR1 is a prefix of STR2"
1613      (eq t (compare-strings str2 nil (length str1) str1 nil nil)))
1614    
1615  (defun tex-guess-main-file (&optional all)  (defun tex-guess-main-file (&optional all)
1616    "Find a likely `tex-main-file'.    "Find a likely `tex-main-file'.
1617  Looks for hints in other buffers in the same directory or in  Looks for hints in other buffers in the same directory or in
1618  ALL other buffers."  ALL other buffers.  If ALL is `sub' only look at buffers in parent directories
1619    of the current buffer."
1620    (let ((dir default-directory)    (let ((dir default-directory)
1621          (header-re tex-start-of-header))          (header-re tex-start-of-header))
1622      (catch 'found      (catch 'found
1623        ;; Look for a buffer with `tex-main-file' set.        ;; Look for a buffer with `tex-main-file' set.
1624        (dolist (buf (if (consp all) all (buffer-list)))        (dolist (buf (if (consp all) all (buffer-list)))
1625          (with-current-buffer buf          (with-current-buffer buf
1626            (when (and (or all (equal dir default-directory))            (when (and (cond
1627                          ((null all) (equal dir default-directory))
1628                          ((eq all 'sub) (tex-string-prefix-p default-directory dir))
1629                          (t))
1630                       (stringp tex-main-file))                       (stringp tex-main-file))
1631              (throw 'found (expand-file-name tex-main-file)))))              (throw 'found (expand-file-name tex-main-file)))))
1632        ;; Look for a buffer containing the magic `tex-start-of-header'.        ;; Look for a buffer containing the magic `tex-start-of-header'.
1633        (dolist (buf (if (consp all) all (buffer-list)))        (dolist (buf (if (consp all) all (buffer-list)))
1634          (with-current-buffer buf          (with-current-buffer buf
1635            (when (and (or all (equal dir default-directory))            (when (and (cond
1636                          ((null all) (equal dir default-directory))
1637                          ((eq all 'sub) (tex-string-prefix-p default-directory dir))
1638                          (t))
1639                       buffer-file-name                       buffer-file-name
1640                       ;; (or (easy-mmode-derived-mode-p 'latex-mode)                       ;; (or (easy-mmode-derived-mode-p 'latex-mode)
1641                       ;;          (easy-mmode-derived-mode-p 'plain-tex-mode))                       ;;          (easy-mmode-derived-mode-p 'plain-tex-mode))
# Line 1539  ALL other buffers." Line 1651  ALL other buffers."
1651    "Return the relative name of the main file."    "Return the relative name of the main file."
1652    (let* ((file (or tex-main-file    (let* ((file (or tex-main-file
1653                     ;; Compatibility with AUCTeX.                     ;; Compatibility with AUCTeX.
1654                     (and (boundp 'TeX-master) (stringp TeX-master)                     (with-no-warnings
1655                          (set (make-local-variable 'tex-main-file) TeX-master))                      (when (and (boundp 'TeX-master) (stringp TeX-master))
1656                          (make-local-variable 'tex-main-file)
1657                          (setq tex-main-file TeX-master)))
1658                     ;; Try to guess the main file.                     ;; Try to guess the main file.
1659                     (if (not buffer-file-name)                     (if (not buffer-file-name)
1660                         (error "Buffer is not associated with any file")                         (error "Buffer is not associated with any file")
# Line 1553  ALL other buffers." Line 1667  ALL other buffers."
1667                            buffer-file-name                            buffer-file-name
1668                          ;; This isn't the main file, let's try to find better,                          ;; This isn't the main file, let's try to find better,
1669                          (or (tex-guess-main-file)                          (or (tex-guess-main-file)
1670                                (tex-guess-main-file 'sub)
1671                              ;; (tex-guess-main-file t)                              ;; (tex-guess-main-file t)
1672                              buffer-file-name)))))))                              buffer-file-name)))))))
1673      (if (file-exists-p file) file (concat file ".tex"))))      (if (file-exists-p file) file (concat file ".tex"))))
1674    
1675    (defun tex-summarize-command (cmd)
1676      (if (not (stringp cmd)) ""
1677        (mapconcat 'identity
1678                   (mapcar (lambda (s) (car (split-string s)))
1679                           (split-string cmd "\\s-*\\(?:;\\|&&\\)\\s-*"))
1680                   "&")))
1681    
1682    (defun tex-uptodate-p (file)
1683      "Return non-nil if FILE is not uptodate w.r.t the document source files.
1684    FILE is typically the output DVI or PDF file."
1685      ;; We should check all the files included !!!
1686      (and
1687       ;; Clearly, the target must exist.
1688       (file-exists-p file)
1689       ;; And the last run must not have asked for a rerun.
1690       ;; FIXME: this should check that the last run was done on the same file.
1691       (let ((buf (condition-case nil (tex-shell-buf) (error nil))))
1692         (when buf
1693           (with-current-buffer buf
1694             (save-excursion
1695               (goto-char (point-max))
1696               (and (re-search-backward
1697                     "(see the transcript file for additional information)" nil t)
1698                    (> (save-excursion
1699                         (or (re-search-backward "\\[[0-9]+\\]" nil t)
1700                             (point-min)))
1701                       (save-excursion
1702                         (or (re-search-backward "Rerun" nil t)
1703                             (point-min)))))))))
1704       ;; And the input files must not have been changed in the meantime.
1705       (let ((files (if (and tex-use-reftex
1706                             (fboundp 'reftex-scanning-info-available-p)
1707                             (reftex-scanning-info-available-p))
1708                        (reftex-all-document-files)
1709                      (list (file-name-directory (expand-file-name file)))))
1710             (ignored-dirs-re
1711              (concat
1712               (regexp-opt
1713                (delq nil (mapcar (lambda (s) (if (eq (aref s (1- (length s))) ?/)
1714                                             (substring s 0 (1- (length s)))))
1715                                  completion-ignored-extensions))
1716                t) "\\'"))
1717             (uptodate t))
1718         (while (and files uptodate)
1719           (let ((f (pop files)))
1720             (if (file-directory-p f)
1721                 (unless (string-match ignored-dirs-re f)
1722                   (setq files (nconc
1723                                (directory-files f t tex-input-files-re)
1724                                files)))
1725               (when (file-newer-than-file-p f file)
1726                 (setq uptodate nil)))))
1727         uptodate)))
1728        
1729    
1730    (autoload 'format-spec "format-spec")
1731    
1732    (defvar tex-executable-cache nil)
1733    (defun tex-executable-exists-p (name)
1734      "Like `executable-find' but with a cache."
1735      (let ((cache (assoc name tex-executable-cache)))
1736        (if cache (cdr cache)
1737          (let ((executable (executable-find name)))
1738            (push (cons name executable) tex-executable-cache)
1739            executable))))
1740    
1741    (defun tex-command-executable (cmd)
1742      (let ((s (if (stringp cmd) cmd (eval (car cmd)))))
1743        (substring s 0 (string-match "[ \t]\\|\\'" s))))
1744    
1745    (defun tex-command-active-p (cmd fspec)
1746      "Return non-nil if the CMD spec might need to be run."
1747      (let ((in (nth 1 cmd))
1748            (out (nth 2 cmd)))
1749        (if (stringp in)
1750            (let ((file (format-spec in fspec)))
1751              (when (file-exists-p file)
1752                (or (not out)
1753                    (file-newer-than-file-p
1754                     file (format-spec out fspec)))))
1755          (when (and (eq in t) (stringp out))
1756            (not (tex-uptodate-p (format-spec out fspec)))))))
1757    
1758    (defun tex-compile-default (fspec)
1759      "Guess a default command given the format-spec FSPEC."
1760      ;; TODO: Learn to do latex+dvips!
1761      (let ((cmds nil)
1762            (unchanged-in nil))
1763        ;; Only consider active commands.
1764        (dolist (cmd tex-compile-commands)
1765          (when (tex-executable-exists-p (tex-command-executable cmd))
1766            (if (tex-command-active-p cmd fspec)
1767                (push cmd cmds)
1768              (push (nth 1 cmd) unchanged-in))))
1769        ;; Remove those commands whose input was considered stable for
1770        ;; some other command (typically if (t . "%.pdf") is inactive
1771        ;; then we're using pdflatex and the fact that the dvi file
1772        ;; is inexistent doesn't matter).
1773        (let ((tmp nil))
1774          (dolist (cmd cmds)
1775            (unless (member (nth 1 cmd) unchanged-in)
1776              (push cmd tmp)))
1777          ;; Only remove if there's something left.
1778          (if tmp (setq cmds tmp)))
1779        ;; Remove commands whose input is not uptodate either.
1780        (let ((outs (delq nil (mapcar (lambda (x) (nth 2 x)) cmds)))
1781              (tmp nil))
1782          (dolist (cmd cmds)
1783            (unless (member (nth 1 cmd) outs)
1784              (push cmd tmp)))
1785          ;; Only remove if there's something left.
1786          (if tmp (setq cmds tmp)))
1787        ;; Select which file we're going to operate on (the latest).
1788        (let ((latest (nth 1 (car cmds))))
1789          (dolist (cmd (prog1 (cdr cmds) (setq cmds (list (car cmds)))))
1790            (if (equal latest (nth 1 cmd))
1791                (push cmd cmds)
1792              (unless (eq latest t)         ;Can't beat that!
1793                (if (or (not (stringp latest))
1794                        (eq (nth 1 cmd) t)
1795                        (and (stringp (nth 1 cmd))
1796                             (file-newer-than-file-p
1797                              (format-spec (nth 1 cmd) fspec)
1798                              (format-spec latest fspec))))
1799                    (setq latest (nth 1 cmd) cmds (list cmd)))))))
1800        ;; Expand the command spec into the actual text.
1801        (dolist (cmd (prog1 cmds (setq cmds nil)))
1802          (push (cons (eval (car cmd)) (cdr cmd)) cmds))
1803        ;; Select the favorite command from the history.
1804        (let ((hist tex-compile-history)
1805              re hist-cmd)
1806          (while hist
1807            (setq hist-cmd (pop hist))
1808            (setq re (concat "\\`"
1809                             (regexp-quote (tex-command-executable hist-cmd))
1810                             "\\([ \t]\\|\\'\\)"))
1811            (dolist (cmd cmds)
1812              ;; If the hist entry uses the same command and applies to a file
1813              ;; of the same type (e.g. `gv %r.pdf' vs `gv %r.ps'), select cmd.
1814              (and (string-match re (car cmd))
1815                   (or (not (string-match "%[fr]\\([-._[:alnum:]]+\\)" (car cmd)))
1816                       (string-match (regexp-quote (match-string 1 (car cmd)))
1817                                     hist-cmd))
1818                   (setq hist nil cmds (list cmd)))))
1819          ;; Substitute and return.
1820          (if (and hist-cmd
1821                   (string-match (concat "[' \t\"]" (format-spec "%r" fspec)
1822                                         "\\([;&' \t\"]\\|\\'\\)") hist-cmd))
1823              ;; The history command was already applied to the same file,
1824              ;; so just reuse it.
1825              hist-cmd
1826            (if cmds (format-spec (caar cmds) fspec))))))
1827    
1828    (defun tex-compile (dir cmd)
1829      "Run a command CMD on current TeX buffer's file in DIR."
1830      ;; FIXME: Use time-stamps on files to decide the next op.
1831      (interactive
1832       (let* ((file (tex-main-file))
1833              (default-directory
1834                (prog1 (file-name-directory (expand-file-name file))
1835                  (setq file (file-name-nondirectory file))))
1836              (root (file-name-sans-extension file))
1837              (fspec (list (cons ?r (comint-quote-filename root))
1838                           (cons ?f (comint-quote-filename file))))
1839              (default (tex-compile-default fspec)))
1840         (list default-directory
1841               (completing-read
1842                (format "Command [%s]: " (tex-summarize-command default))
1843                (mapcar (lambda (x)
1844                          (list (format-spec (eval (car x)) fspec)))
1845                        tex-compile-commands)
1846                nil nil nil 'tex-compile-history default))))
1847      (save-some-buffers (not compilation-ask-about-save) nil)
1848      (if (tex-shell-running)
1849          (tex-kill-job)
1850        (tex-start-shell))
1851      (tex-send-tex-command cmd dir))
1852    
1853  (defun tex-start-tex (command file &optional dir)  (defun tex-start-tex (command file &optional dir)
1854    "Start a TeX run, using COMMAND on FILE."    "Start a TeX run, using COMMAND on FILE."
# Line 1844  The last line of the buffer is displayed Line 2136  The last line of the buffer is displayed
2136  line LINE of the window, or centered if LINE is nil."  line LINE of the window, or centered if LINE is nil."
2137    (interactive "P")    (interactive "P")
2138    (let ((tex-shell (get-buffer "*tex-shell*"))    (let ((tex-shell (get-buffer "*tex-shell*"))
         (old-buffer (current-buffer))  
2139          (window))          (window))
2140      (if (null tex-shell)      (if (null tex-shell)
2141          (message "No TeX output buffer")          (message "No TeX output buffer")
# Line 1961  Runs the shell command defined by `tex-s Line 2252  Runs the shell command defined by `tex-s
2252  (defvar tex-indent-item tex-indent-basic)  (defvar tex-indent-item tex-indent-basic)
2253  (defvar tex-indent-item-re "\\\\\\(bib\\)?item\\>")  (defvar tex-indent-item-re "\\\\\\(bib\\)?item\\>")
2254    
2255  (easy-mmode-defsyntax tex-latex-indent-syntax-table  (defvar tex-latex-indent-syntax-table
2256    '((?$ . ".")    (let ((st (make-syntax-table tex-mode-syntax-table)))
2257      (?\( . ".")      (modify-syntax-entry ?$ "." st)
2258      (?\) . "."))      (modify-syntax-entry ?\( "." st)
2259    "Syntax table used while computing indentation."      (modify-syntax-entry ?\) "." st)
2260    :copy tex-mode-syntax-table)      st)
2261      "Syntax table used while computing indentation.")
2262    
2263  (defun latex-indent (&optional arg)  (defun latex-indent (&optional arg)
2264    (if (and (eq (get-text-property (line-beginning-position) 'face)    (if (and (eq (get-text-property (line-beginning-position) 'face)
2265                 tex-verbatim-face))                 tex-verbatim-face))
2266        (indent-relative)        'noindent
2267      (with-syntax-table tex-latex-indent-syntax-table      (with-syntax-table tex-latex-indent-syntax-table
2268        ;; TODO: Rather than ignore $, we should try to be more clever about it.        ;; TODO: Rather than ignore $, we should try to be more clever about it.
2269        (let ((indent        (let ((indent
# Line 2058  There might be text before point." Line 2350  There might be text before point."
2350                   (min (current-column) (+ tex-indent-arg col))                   (min (current-column) (+ tex-indent-arg col))
2351                 (skip-syntax-forward " ")                 (skip-syntax-forward " ")
2352                 (current-column))))))))))                 (current-column))))))))))
2353    ;;; DocTeX support
2354    
2355    (defun doctex-font-lock-^^A ()
2356      (if (eq (char-after (line-beginning-position)) ?\%)
2357          (progn
2358            (put-text-property
2359             (1- (match-beginning 1)) (match-beginning 1)
2360             'syntax-table
2361             (if (= (1+ (line-beginning-position)) (match-beginning 1))
2362                 ;; The `%' is a single-char comment, which Emacs
2363                 ;; syntax-table can't deal with.  We could turn it
2364                 ;; into a non-comment, or use `\n%' or `%^' as the comment.
2365                 ;; Instead, we include it in the ^^A comment.
2366                 (eval-when-compile (string-to-syntax "< b"))
2367               (eval-when-compile (string-to-syntax ">"))))
2368            (let ((end (line-end-position)))
2369              (if (< end (point-max))
2370                  (put-text-property
2371                   end (1+ end)
2372                   'syntax-table
2373                   (eval-when-compile (string-to-syntax "> b")))))
2374            (eval-when-compile (string-to-syntax "< b")))))
2375    
2376    (defun doctex-font-lock-syntactic-face-function (state)
2377      ;; Mark DocTeX documentation, which is parsed as a style A comment
2378      ;; starting in column 0.
2379      (if (or (nth 3 state) (nth 7 state)
2380              (not (memq (char-before (nth 8 state))
2381                         '(?\n nil))))
2382          ;; Anything else is just as for LaTeX.
2383          (tex-font-lock-syntactic-face-function state)
2384        font-lock-doc-face))
2385    
2386    (defvar doctex-font-lock-syntactic-keywords
2387      (append
2388       tex-font-lock-syntactic-keywords
2389       ;; For DocTeX comment-in-doc.
2390       `(("\\(\\^\\)\\^A" (1 (doctex-font-lock-^^A))))))
2391    
2392    (defvar doctex-font-lock-keywords
2393      (append tex-font-lock-keywords
2394              '(("^%<[^>]*>" (0 font-lock-preprocessor-face t)))))
2395    
2396    ;;;###autoload
2397    (define-derived-mode doctex-mode latex-mode "DocTeX"
2398      "Major mode to edit DocTeX files."
2399      (setq font-lock-defaults
2400            (cons (append (car font-lock-defaults) '(doctex-font-lock-keywords))
2401                  (mapcar
2402                   (lambda (x)
2403                     (case (car-safe x)
2404                       (font-lock-syntactic-keywords
2405                        (cons (car x) 'doctex-font-lock-syntactic-keywords))
2406                       (font-lock-syntactic-face-function
2407                        (cons (car x) 'doctex-font-lock-syntactic-face-function))
2408                       (t x)))
2409                   (cdr font-lock-defaults)))))
2410    
2411  (run-hooks 'tex-mode-load-hook)  (run-hooks 'tex-mode-load-hook)
2412    
2413  (provide 'tex-mode)  (provide 'tex-mode)
2414    
2415    ;;; arch-tag: c0a680b1-63aa-4547-84b9-4193c29c0080
2416  ;;; tex-mode.el ends here  ;;; tex-mode.el ends here

Legend:
Removed from v.1.123.2.1  
changed lines
  Added in v.1.123.2.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26