emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/lisp/textmodes/tex-mode.el [lexbind]


From: Miles Bader
Subject: [Emacs-diffs] Changes to emacs/lisp/textmodes/tex-mode.el [lexbind]
Date: Tue, 14 Oct 2003 19:30:38 -0400

Index: emacs/lisp/textmodes/tex-mode.el
diff -c emacs/lisp/textmodes/tex-mode.el:1.123.2.1 
emacs/lisp/textmodes/tex-mode.el:1.123.2.2
*** emacs/lisp/textmodes/tex-mode.el:1.123.2.1  Fri Apr  4 01:20:40 2003
--- emacs/lisp/textmodes/tex-mode.el    Tue Oct 14 19:30:22 2003
***************
*** 1,6 ****
  ;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands -*- coding: utf-8 -*-
  
! ;; Copyright (C) 1985, 86, 89, 92, 94, 95, 96, 97, 98, 1999, 2002
  ;;       Free Software Foundation, Inc.
  
  ;; Maintainer: FSF
--- 1,6 ----
  ;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands -*- coding: utf-8 -*-
  
! ;; Copyright (C) 1985,86,89,92,94,95,96,97,98,1999,2002,2003
  ;;       Free Software Foundation, Inc.
  
  ;; Maintainer: FSF
***************
*** 196,202 ****
    :group 'tex-view)
  
  ;;;###autoload
! (defcustom tex-dvi-view-command '(if (eq window-system 'x) \"xdvi\" \"dvi2tty 
* | cat -s\")
    "*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;
--- 196,202 ----
    :group 'tex-view)
  
  ;;;###autoload
! (defcustom tex-dvi-view-command '(if (eq window-system 'x) "xdvi" "dvi2tty * 
| cat -s")
    "*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;
***************
*** 276,297 ****
    "File name that \\[tex-print] prints.
  Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].")
  
! (easy-mmode-defsyntax tex-mode-syntax-table
!   '((?% . "<")
!     (?\n . ">")
!     (?\f . ">")
!     (?\C-@ . "w")
!     (?' . "w")
!     (?@ . "_")
!     (?* . "_")
!     (?\t . " ")
!     (?~ . " ")
!     (?$ . "$$")
!     (?\\ . "/")
!     (?\" . ".")
!     (?& . ".")
!     (?_ . ".")
!     (?^ . "."))
    "Syntax table used while in TeX mode.")
  
  ;;;;
--- 276,301 ----
    "File name that \\[tex-print] prints.
  Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].")
  
! (defvar tex-mode-syntax-table
!   (let ((st (make-syntax-table)))
!     (modify-syntax-entry ?% "<" st)
!     (modify-syntax-entry ?\n ">" st)
!     (modify-syntax-entry ?\f ">" st)
!     (modify-syntax-entry ?\C-@ "w" st)
!     (modify-syntax-entry ?' "w" st)
!     (modify-syntax-entry ?@ "_" st)
!     (modify-syntax-entry ?* "_" st)
!     (modify-syntax-entry ?\t " " st)
!     ;; ~ is printed by TeX as a space, but it's semantics in the syntax
!     ;; of TeX is not `whitespace' (i.e. it's just like \hspace{foo}).
!     (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)
!     st)
    "Syntax table used while in TeX mode.")
  
  ;;;;
***************
*** 499,505 ****
            (bold (regexp-opt '("textbf" "textsc" "textup"
                                "boldsymbol" "pmb") t))
            (italic (regexp-opt '("textit" "textsl" "emph") t))
!           (type (regexp-opt '("texttt" "textmd" "textrm" "textsf") t))
            ;;
            ;; Names of commands whose arg should be fontified as a citation.
            (citations (regexp-opt
--- 503,510 ----
            (bold (regexp-opt '("textbf" "textsc" "textup"
                                "boldsymbol" "pmb") t))
            (italic (regexp-opt '("textit" "textsl" "emph") t))
!           ;; FIXME: unimplemented yet.
!           ;; (type (regexp-opt '("texttt" "textmd" "textrm" "textsf") t))
            ;;
            ;; Names of commands whose arg should be fontified as a citation.
            (citations (regexp-opt
***************
*** 690,695 ****
--- 695,701 ----
      (define-key map "\C-c\C-r" 'tex-region)
      (define-key map "\C-c\C-b" 'tex-buffer)
      (define-key map "\C-c\C-f" 'tex-file)
+     (define-key map "\C-c\C-c" 'tex-compile)
      (define-key map "\C-c\C-i" 'tex-bibtex-file)
      (define-key map "\C-c\C-o" 'latex-insert-block)
      (define-key map "\C-c\C-e" 'latex-close-block)
***************
*** 713,718 ****
--- 719,725 ----
  (defvar latex-mode-map
    (let ((map (make-sparse-keymap)))
      (set-keymap-parent map tex-mode-map)
+     (define-key map "\C-c\C-s" 'latex-split-block)
      map)
    "Keymap for `latex-mode'.  See also `tex-mode-map'.")
  
***************
*** 745,759 ****
  
  ;; This would be a lot simpler if we just used a regexp search,
  ;; but then it would be too slow.
! ;;;###autoload
! (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)
    (let ((mode tex-default-mode) slash comment)
      (save-excursion
        (goto-char (point-min))
--- 752,758 ----
  
  ;; This would be a lot simpler if we just used a regexp search,
  ;; but then it would be too slow.
! (defun tex-guess-mode ()
    (let ((mode tex-default-mode) slash comment)
      (save-excursion
        (goto-char (point-min))
***************
*** 769,775 ****
                     (concat
                      (regexp-opt '("documentstyle" "documentclass"
                                    "begin" "subsection" "section"
!                                   "part" "chapter" "newcommand") 'words)
                      "\\|NeedsTeXFormat{LaTeX")))
                  (if (looking-at
                       "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}")
--- 768,775 ----
                     (concat
                      (regexp-opt '("documentstyle" "documentclass"
                                    "begin" "subsection" "section"
!                                   "part" "chapter" "newcommand"
!                                   "renewcommand") 'words)
                      "\\|NeedsTeXFormat{LaTeX")))
                  (if (looking-at
                       "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}")
***************
*** 778,783 ****
--- 778,809 ----
                'plain-tex-mode))))
      (funcall mode)))
  
+ ;; `tex-mode' plays two roles: it's the parent of several sub-modes
+ ;; but it's also the function that chooses between those submodes.
+ ;; To tell the difference between those two cases where the function
+ ;; might be called, we check `delay-mode-hooks'.
+ (define-derived-mode tex-mode text-mode "generic-TeX"
+   (tex-common-initialization))
+ ;; We now move the function and define it again.  This gives a warning
+ ;; in the byte-compiler :-( but it's difficult to avoid because
+ ;; `define-derived-mode' will necessarily define the function once
+ ;; and we need to define it a second time for `autoload' to get the
+ ;; proper docstring.
+ (defalias 'tex-mode-internal (symbol-function 'tex-mode))
+ ;;;###autoload
+ (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)
+   (if delay-mode-hooks
+       ;; We're called from one of the children already.
+       (tex-mode-internal)
+     (tex-guess-mode)))
+ 
  ;;;###autoload
  (defalias 'TeX-mode 'tex-mode)
  ;;;###autoload
***************
*** 786,792 ****
  (defalias 'LaTeX-mode 'latex-mode)
  
  ;;;###autoload
! (define-derived-mode plain-tex-mode text-mode "TeX"
    "Major mode for editing files of input for plain TeX.
  Makes $ and } display the characters they match.
  Makes \" insert `` when it seems to be the beginning of a quotation,
--- 812,818 ----
  (defalias 'LaTeX-mode 'latex-mode)
  
  ;;;###autoload
! (define-derived-mode plain-tex-mode tex-mode "TeX"
    "Major mode for editing files of input for plain TeX.
  Makes $ and } display the characters they match.
  Makes \" insert `` when it seems to be the beginning of a quotation,
***************
*** 826,840 ****
  Entering Plain-tex mode runs the hook `text-mode-hook', then the hook
  `tex-mode-hook', and finally the hook `plain-tex-mode-hook'.  When the
  special subshell is initiated, the hook `tex-shell-hook' is run."
!   (tex-common-initialization)
!   (setq tex-command tex-run-command)
!   (setq tex-start-of-header "%\\*\\*start of header")
!   (setq tex-end-of-header "%\\*\\*end of header")
!   (setq tex-trailer "\\bye\n")
!   (run-hooks 'tex-mode-hook))
  
  ;;;###autoload
! (define-derived-mode latex-mode text-mode "LaTeX"
    "Major mode for editing files of input for LaTeX.
  Makes $ and } display the characters they match.
  Makes \" insert `` when it seems to be the beginning of a quotation,
--- 852,864 ----
  Entering Plain-tex mode runs the hook `text-mode-hook', then the hook
  `tex-mode-hook', and finally the hook `plain-tex-mode-hook'.  When the
  special subshell is initiated, the hook `tex-shell-hook' is run."
!   (set (make-local-variable 'tex-command) tex-run-command)
!   (set (make-local-variable 'tex-start-of-header) "%\\*\\*start of header")
!   (set (make-local-variable 'tex-end-of-header) "%\\*\\*end of header")
!   (set (make-local-variable 'tex-trailer) "\\bye\n"))
  
  ;;;###autoload
! (define-derived-mode latex-mode tex-mode "LaTeX"
    "Major mode for editing files of input for LaTeX.
  Makes $ and } display the characters they match.
  Makes \" insert `` when it seems to be the beginning of a quotation,
***************
*** 874,889 ****
  Entering Latex mode runs the hook `text-mode-hook', then
  `tex-mode-hook', and finally `latex-mode-hook'.  When the special
  subshell is initiated, `tex-shell-hook' is run."
!   (tex-common-initialization)
!   (setq tex-command latex-run-command)
!   (setq tex-start-of-header "\\\\document\\(style\\|class\\)")
!   (setq tex-end-of-header "\\\\begin\\s-*{document}")
!   (setq tex-trailer "\\end\\s-*{document}\n")
    ;; A line containing just $$ is treated as a paragraph separator.
    ;; A line starting with $$ starts a paragraph,
    ;; but does not separate paragraphs if it has more stuff on it.
    (setq paragraph-start
!       (concat "[\f%]\\|[ \t]*\\($\\|\\$\\$\\|"
                "\\\\[][]\\|"
                "\\\\" (regexp-opt (append
                                    (mapcar 'car latex-section-alist)
--- 898,913 ----
  Entering Latex mode runs the hook `text-mode-hook', then
  `tex-mode-hook', and finally `latex-mode-hook'.  When the special
  subshell is initiated, `tex-shell-hook' is run."
!   (set (make-local-variable 'tex-command) latex-run-command)
!   (set (make-local-variable 'tex-start-of-header)
!        "\\\\document\\(style\\|class\\)")
!   (set (make-local-variable 'tex-end-of-header) "\\\\begin\\s-*{document}")
!   (set (make-local-variable 'tex-trailer) "\\end\\s-*{document}\n")
    ;; A line containing just $$ is treated as a paragraph separator.
    ;; A line starting with $$ starts a paragraph,
    ;; but does not separate paragraphs if it has more stuff on it.
    (setq paragraph-start
!       (concat "[ \t]*\\(\\$\\$\\|"
                "\\\\[][]\\|"
                "\\\\" (regexp-opt (append
                                    (mapcar 'car latex-section-alist)
***************
*** 913,920 ****
    (set (make-local-variable 'outline-regexp) latex-outline-regexp)
    (set (make-local-variable 'outline-level) 'latex-outline-level)
    (set (make-local-variable 'forward-sexp-function) 'latex-forward-sexp)
!   (set (make-local-variable 'skeleton-end-hook) nil)
!   (run-hooks 'tex-mode-hook))
  
  ;;;###autoload
  (define-derived-mode slitex-mode latex-mode "SliTeX"
--- 937,943 ----
    (set (make-local-variable 'outline-regexp) latex-outline-regexp)
    (set (make-local-variable 'outline-level) 'latex-outline-level)
    (set (make-local-variable 'forward-sexp-function) 'latex-forward-sexp)
!   (set (make-local-variable 'skeleton-end-hook) nil))
  
  ;;;###autoload
  (define-derived-mode slitex-mode latex-mode "SliTeX"
***************
*** 962,968 ****
    (setq tex-start-of-header 
"\\\\documentstyle{slides}\\|\\\\documentclass{slides}"))
  
  (defun tex-common-initialization ()
-   (set-syntax-table tex-mode-syntax-table)
    ;; Regexp isearch should accept newline and formfeed as whitespace.
    (set (make-local-variable 'search-whitespace-regexp) "[ \t\r\n\f]+")
    ;; A line containing just $$ is treated as a paragraph separator.
--- 985,990 ----
***************
*** 1069,1076 ****
        (num-matches 0))
      (with-output-to-temp-buffer "*Occur*"
        (princ "Mismatches:\n")
!       (save-excursion
!       (set-buffer standard-output)
        (occur-mode)
        ;; This won't actually work...Really, this whole thing should
        ;; be rewritten instead of being a hack on top of occur.
--- 1091,1097 ----
        (num-matches 0))
      (with-output-to-temp-buffer "*Occur*"
        (princ "Mismatches:\n")
!       (with-current-buffer standard-output
        (occur-mode)
        ;; This won't actually work...Really, this whole thing should
        ;; be rewritten instead of being a hack on top of occur.
***************
*** 1087,1094 ****
                  (forward-char 2))
              (goto-char (setq prev-end (point-min))))
            (or (tex-validate-region (point) end)
!               (let* ((oend end)
!                      (end (save-excursion (forward-line 1) (point)))
                       start tem)
                  (beginning-of-line)
                  (setq start (point))
--- 1108,1114 ----
                  (forward-char 2))
              (goto-char (setq prev-end (point-min))))
            (or (tex-validate-region (point) end)
!               (let* ((end (line-beginning-position 2))
                       start tem)
                  (beginning-of-line)
                  (setq start (point))
***************
*** 1194,1203 ****
  
  (defvar latex-block-default "enumerate")
  
  ;; Like tex-insert-braces, but for LaTeX.
  (defalias 'tex-latex-block 'latex-insert-block)
  (define-skeleton latex-insert-block
!   "Create a matching pair of lines \\begin[OPT]{NAME} and \\end{NAME} at 
point.
  Puts point on a blank line between them."
    (let ((choice (completing-read (format "LaTeX block name [%s]: "
                                         latex-block-default)
--- 1214,1241 ----
  
  (defvar latex-block-default "enumerate")
  
+ (defvar latex-block-args-alist
+   '(("array" nil ?\{ (skeleton-read "[options]: ") ?\})
+     ("tabular" nil ?\{ (skeleton-read "[options]: ") ?\}))
+   "Skeleton element to use for arguments to particular environments.
+ Every element of the list has the form (NAME . SKEL-ELEM) where NAME is
+ the name of the environment and SKEL-ELEM is an element to use in
+ a skeleton (see `skeleton-insert').")
+ 
+ (defvar latex-block-body-alist
+   '(("enumerate" nil '(latex-insert-item) > _)
+     ("itemize" nil '(latex-insert-item) > _)
+     ("table" nil "\\caption{" > - "}" > \n _)
+     ("figure" nil  > _ \n "\\caption{" > _ "}" >))
+   "Skeleton element to use for the body of particular environments.
+ Every element of the list has the form (NAME . SKEL-ELEM) where NAME is
+ the name of the environment and SKEL-ELEM is an element to use in
+ a skeleton (see `skeleton-insert').")
+ 
  ;; Like tex-insert-braces, but for LaTeX.
  (defalias 'tex-latex-block 'latex-insert-block)
  (define-skeleton latex-insert-block
!   "Create a matching pair of lines \\begin{NAME} and \\end{NAME} at point.
  Puts point on a blank line between them."
    (let ((choice (completing-read (format "LaTeX block name [%s]: "
                                         latex-block-default)
***************
*** 1211,1218 ****
        (push choice latex-block-names))
      choice)
    \n "\\begin{" str "}"
!   ?\[ (skeleton-read "[options]: ") & ?\] | -1
!   > \n _ \n
    "\\end{" str "}" > \n)
  
  (define-skeleton latex-insert-item
--- 1249,1256 ----
        (push choice latex-block-names))
      choice)
    \n "\\begin{" str "}"
!   (cdr (assoc str latex-block-args-alist))
!   > \n (or (cdr (assoc str latex-block-body-alist)) '(nil > _)) \n
    "\\end{" str "}" > \n)
  
  (define-skeleton latex-insert-item
***************
*** 1225,1241 ****
  ;;;; LaTeX syntax navigation
  ;;;;
  
  (defun tex-last-unended-begin ()
    "Leave point at the beginning of the last `\\begin{...}' that is unended."
    (condition-case nil
!       (while (and (re-search-backward "\\\\\\(begin\\|end\\)\\s *{")
                  (looking-at "\\\\end"))
        (tex-last-unended-begin))
      (search-failed (error "Couldn't find unended \\begin"))))
  
  (defun tex-next-unmatched-end ()
    "Leave point at the end of the next `\\end' that is unended."
!   (while (and (re-search-forward "\\\\\\(begin\\|end\\)\\s *{[^}]+}")
              (save-excursion (goto-char (match-beginning 0))
                              (looking-at "\\\\begin")))
      (tex-next-unmatched-end)))
--- 1263,1292 ----
  ;;;; LaTeX syntax navigation
  ;;;;
  
+ (defmacro tex-search-noncomment (&rest body)
+   "Execute BODY as long as it return non-nil and point is in a comment.
+ Return the value returned by the last execution of BODY."
+   (declare (debug t))
+   (let ((res-sym (make-symbol "result")))
+     `(let (,res-sym)
+        (while
+          (and (setq ,res-sym (progn ,@body))
+               (save-excursion (skip-chars-backward "^\n%") (not (bolp)))))
+        ,res-sym)))
+ 
  (defun tex-last-unended-begin ()
    "Leave point at the beginning of the last `\\begin{...}' that is unended."
    (condition-case nil
!       (while (and (tex-search-noncomment
!                  (re-search-backward "\\\\\\(begin\\|end\\)\\s *{"))
                  (looking-at "\\\\end"))
        (tex-last-unended-begin))
      (search-failed (error "Couldn't find unended \\begin"))))
  
  (defun tex-next-unmatched-end ()
    "Leave point at the end of the next `\\end' that is unended."
!   (while (and (tex-search-noncomment
!              (re-search-forward "\\\\\\(begin\\|end\\)\\s *{[^}]+}"))
              (save-excursion (goto-char (match-beginning 0))
                              (looking-at "\\\\begin")))
      (tex-next-unmatched-end)))
***************
*** 1507,1529 ****
  
  (add-hook 'kill-emacs-hook 'tex-delete-last-temp-files)
  
  (defun tex-guess-main-file (&optional all)
    "Find a likely `tex-main-file'.
  Looks for hints in other buffers in the same directory or in
! ALL other buffers."
    (let ((dir default-directory)
        (header-re tex-start-of-header))
      (catch 'found
        ;; Look for a buffer with `tex-main-file' set.
        (dolist (buf (if (consp all) all (buffer-list)))
        (with-current-buffer buf
!         (when (and (or all (equal dir default-directory))
                     (stringp tex-main-file))
            (throw 'found (expand-file-name tex-main-file)))))
        ;; Look for a buffer containing the magic `tex-start-of-header'.
        (dolist (buf (if (consp all) all (buffer-list)))
        (with-current-buffer buf
!         (when (and (or all (equal dir default-directory))
                     buffer-file-name
                     ;; (or (easy-mmode-derived-mode-p 'latex-mode)
                     ;;          (easy-mmode-derived-mode-p 'plain-tex-mode))
--- 1558,1641 ----
  
  (add-hook 'kill-emacs-hook 'tex-delete-last-temp-files)
  
+ ;;
+ ;; Machinery to guess the command that the user wants to execute.
+ ;;
+ 
+ (defvar tex-compile-history nil)
+ 
+ (defvar tex-input-files-re
+   (eval-when-compile
+     (concat "\\." (regexp-opt '("tex" "texi" "texinfo"
+                               "bbl" "ind" "sty" "cls") t)
+           ;; Include files with no dots (for directories).
+           "\\'\\|\\`[^.]+\\'")))
+ 
+ (defcustom tex-use-reftex t
+   "If non-nil, use RefTeX's list of files to determine what command to use."
+   :type 'boolean)
+ 
+ (defvar tex-compile-commands
+   '(((concat "pdf" tex-command
+            " " (if (< 0 (length tex-start-commands))
+                    (shell-quote-argument tex-start-commands)) " %f")
+      t "%r.pdf")
+     ((concat tex-command
+            " " (if (< 0 (length tex-start-commands))
+                    (shell-quote-argument tex-start-commands)) " %f")
+      t "%r.dvi")
+     ("xdvi %r &" "%r.dvi")
+     ("advi %r &" "%r.dvi")
+     ("bibtex %r" "%r.aux" "%r.bbl")
+     ("makeindex %r" "%r.idx" "%r.ind")
+     ("texindex %r.??")
+     ("dvipdfm %r" "%r.dvi" "%r.pdf")
+     ("dvipdf %r" "%r.dvi" "%r.pdf")
+     ("dvips %r" "%r.dvi" "%r.ps")
+     ("gv %r.ps &" "%r.ps")
+     ("gv %r.pdf &" "%r.pdf")
+     ("xpdf %r.pdf &" "%r.pdf")
+     ("lpr %r.ps" "%r.ps"))
+   "List of commands for `tex-compile'.
+ Each element should be of the form (FORMAT IN OUT) where
+ FORMAT is an expression that evaluates to a string that can contain
+   - `%r' the main file name without extension.
+   - `%f' the main file name.
+ IN can be either a string (with the same % escapes in it) indicating
+   the name of the input file, or t to indicate that the input is all
+   the TeX files of the document, or nil if we don't know.
+ OUT describes the output file and is either a %-escaped string
+   or nil to indicate that there is no output file.")
+ 
+ ;; defsubst* gives better byte-code than defsubst.
+ (defsubst* tex-string-prefix-p (str1 str2)
+   "Return non-nil if STR1 is a prefix of STR2"
+   (eq t (compare-strings str2 nil (length str1) str1 nil nil)))
+ 
  (defun tex-guess-main-file (&optional all)
    "Find a likely `tex-main-file'.
  Looks for hints in other buffers in the same directory or in
! ALL other buffers.  If ALL is `sub' only look at buffers in parent directories
! of the current buffer."
    (let ((dir default-directory)
        (header-re tex-start-of-header))
      (catch 'found
        ;; Look for a buffer with `tex-main-file' set.
        (dolist (buf (if (consp all) all (buffer-list)))
        (with-current-buffer buf
!         (when (and (cond
!                     ((null all) (equal dir default-directory))
!                     ((eq all 'sub) (tex-string-prefix-p default-directory 
dir))
!                     (t))
                     (stringp tex-main-file))
            (throw 'found (expand-file-name tex-main-file)))))
        ;; Look for a buffer containing the magic `tex-start-of-header'.
        (dolist (buf (if (consp all) all (buffer-list)))
        (with-current-buffer buf
!         (when (and (cond
!                     ((null all) (equal dir default-directory))
!                     ((eq all 'sub) (tex-string-prefix-p default-directory 
dir))
!                     (t))
                     buffer-file-name
                     ;; (or (easy-mmode-derived-mode-p 'latex-mode)
                     ;;          (easy-mmode-derived-mode-p 'plain-tex-mode))
***************
*** 1539,1546 ****
    "Return the relative name of the main file."
    (let* ((file (or tex-main-file
                   ;; Compatibility with AUCTeX.
!                  (and (boundp 'TeX-master) (stringp TeX-master)
!                       (set (make-local-variable 'tex-main-file) TeX-master))
                   ;; Try to guess the main file.
                   (if (not buffer-file-name)
                       (error "Buffer is not associated with any file")
--- 1651,1660 ----
    "Return the relative name of the main file."
    (let* ((file (or tex-main-file
                   ;; Compatibility with AUCTeX.
!                  (with-no-warnings
!                   (when (and (boundp 'TeX-master) (stringp TeX-master))
!                     (make-local-variable 'tex-main-file)
!                     (setq tex-main-file TeX-master)))
                   ;; Try to guess the main file.
                   (if (not buffer-file-name)
                       (error "Buffer is not associated with any file")
***************
*** 1553,1562 ****
--- 1667,1854 ----
                          buffer-file-name
                        ;; This isn't the main file, let's try to find better,
                        (or (tex-guess-main-file)
+                           (tex-guess-main-file 'sub)
                            ;; (tex-guess-main-file t)
                            buffer-file-name)))))))
      (if (file-exists-p file) file (concat file ".tex"))))
  
+ (defun tex-summarize-command (cmd)
+   (if (not (stringp cmd)) ""
+     (mapconcat 'identity
+              (mapcar (lambda (s) (car (split-string s)))
+                      (split-string cmd "\\s-*\\(?:;\\|&&\\)\\s-*"))
+              "&")))
+ 
+ (defun tex-uptodate-p (file)
+   "Return non-nil if FILE is not uptodate w.r.t the document source files.
+ FILE is typically the output DVI or PDF file."
+   ;; We should check all the files included !!!
+   (and
+    ;; Clearly, the target must exist.
+    (file-exists-p file)
+    ;; And the last run must not have asked for a rerun.
+    ;; FIXME: this should check that the last run was done on the same file.
+    (let ((buf (condition-case nil (tex-shell-buf) (error nil))))
+      (when buf
+        (with-current-buffer buf
+        (save-excursion
+          (goto-char (point-max))
+          (and (re-search-backward
+                "(see the transcript file for additional information)" nil t)
+               (> (save-excursion
+                    (or (re-search-backward "\\[[0-9]+\\]" nil t)
+                        (point-min)))
+                  (save-excursion
+                    (or (re-search-backward "Rerun" nil t)
+                        (point-min)))))))))
+    ;; And the input files must not have been changed in the meantime.
+    (let ((files (if (and tex-use-reftex
+                        (fboundp 'reftex-scanning-info-available-p)
+                        (reftex-scanning-info-available-p))
+                   (reftex-all-document-files)
+                 (list (file-name-directory (expand-file-name file)))))
+        (ignored-dirs-re
+         (concat
+          (regexp-opt
+           (delq nil (mapcar (lambda (s) (if (eq (aref s (1- (length s))) ?/)
+                                        (substring s 0 (1- (length s)))))
+                             completion-ignored-extensions))
+           t) "\\'"))
+        (uptodate t))
+      (while (and files uptodate)
+        (let ((f (pop files)))
+        (if (file-directory-p f)
+            (unless (string-match ignored-dirs-re f)
+              (setq files (nconc
+                           (directory-files f t tex-input-files-re)
+                           files)))
+          (when (file-newer-than-file-p f file)
+            (setq uptodate nil)))))
+      uptodate)))
+     
+ 
+ (autoload 'format-spec "format-spec")
+ 
+ (defvar tex-executable-cache nil)
+ (defun tex-executable-exists-p (name)
+   "Like `executable-find' but with a cache."
+   (let ((cache (assoc name tex-executable-cache)))
+     (if cache (cdr cache)
+       (let ((executable (executable-find name)))
+       (push (cons name executable) tex-executable-cache)
+       executable))))
+ 
+ (defun tex-command-executable (cmd)
+   (let ((s (if (stringp cmd) cmd (eval (car cmd)))))
+     (substring s 0 (string-match "[ \t]\\|\\'" s))))
+ 
+ (defun tex-command-active-p (cmd fspec)
+   "Return non-nil if the CMD spec might need to be run."
+   (let ((in (nth 1 cmd))
+       (out (nth 2 cmd)))
+     (if (stringp in)
+       (let ((file (format-spec in fspec)))
+         (when (file-exists-p file)
+           (or (not out)
+               (file-newer-than-file-p
+                file (format-spec out fspec)))))
+       (when (and (eq in t) (stringp out))
+       (not (tex-uptodate-p (format-spec out fspec)))))))
+ 
+ (defun tex-compile-default (fspec)
+   "Guess a default command given the format-spec FSPEC."
+   ;; TODO: Learn to do latex+dvips!
+   (let ((cmds nil)
+       (unchanged-in nil))
+     ;; Only consider active commands.
+     (dolist (cmd tex-compile-commands)
+       (when (tex-executable-exists-p (tex-command-executable cmd))
+       (if (tex-command-active-p cmd fspec)
+           (push cmd cmds)
+         (push (nth 1 cmd) unchanged-in))))
+     ;; Remove those commands whose input was considered stable for
+     ;; some other command (typically if (t . "%.pdf") is inactive
+     ;; then we're using pdflatex and the fact that the dvi file
+     ;; is inexistent doesn't matter).
+     (let ((tmp nil))
+       (dolist (cmd cmds)
+       (unless (member (nth 1 cmd) unchanged-in)
+         (push cmd tmp)))
+       ;; Only remove if there's something left.
+       (if tmp (setq cmds tmp)))
+     ;; Remove commands whose input is not uptodate either.
+     (let ((outs (delq nil (mapcar (lambda (x) (nth 2 x)) cmds)))
+         (tmp nil))
+       (dolist (cmd cmds)
+       (unless (member (nth 1 cmd) outs)
+         (push cmd tmp)))
+       ;; Only remove if there's something left.
+       (if tmp (setq cmds tmp)))
+     ;; Select which file we're going to operate on (the latest).
+     (let ((latest (nth 1 (car cmds))))
+       (dolist (cmd (prog1 (cdr cmds) (setq cmds (list (car cmds)))))
+       (if (equal latest (nth 1 cmd))
+           (push cmd cmds)
+         (unless (eq latest t)         ;Can't beat that!
+           (if (or (not (stringp latest))
+                   (eq (nth 1 cmd) t)
+                   (and (stringp (nth 1 cmd))
+                        (file-newer-than-file-p
+                         (format-spec (nth 1 cmd) fspec)
+                         (format-spec latest fspec))))
+               (setq latest (nth 1 cmd) cmds (list cmd)))))))
+     ;; Expand the command spec into the actual text.
+     (dolist (cmd (prog1 cmds (setq cmds nil)))
+       (push (cons (eval (car cmd)) (cdr cmd)) cmds))
+     ;; Select the favorite command from the history.
+     (let ((hist tex-compile-history)
+         re hist-cmd)
+       (while hist
+       (setq hist-cmd (pop hist))
+       (setq re (concat "\\`"
+                        (regexp-quote (tex-command-executable hist-cmd))
+                        "\\([ \t]\\|\\'\\)"))
+       (dolist (cmd cmds)
+         ;; If the hist entry uses the same command and applies to a file
+         ;; of the same type (e.g. `gv %r.pdf' vs `gv %r.ps'), select cmd.
+         (and (string-match re (car cmd))
+              (or (not (string-match "%[fr]\\([-._[:alnum:]]+\\)" (car cmd)))
+                  (string-match (regexp-quote (match-string 1 (car cmd)))
+                                hist-cmd))
+              (setq hist nil cmds (list cmd)))))
+       ;; Substitute and return.
+       (if (and hist-cmd
+              (string-match (concat "[' \t\"]" (format-spec "%r" fspec)
+                                    "\\([;&' \t\"]\\|\\'\\)") hist-cmd))
+         ;; The history command was already applied to the same file,
+         ;; so just reuse it.
+         hist-cmd
+       (if cmds (format-spec (caar cmds) fspec))))))
+ 
+ (defun tex-compile (dir cmd)
+   "Run a command CMD on current TeX buffer's file in DIR."
+   ;; FIXME: Use time-stamps on files to decide the next op.
+   (interactive
+    (let* ((file (tex-main-file))
+         (default-directory
+           (prog1 (file-name-directory (expand-file-name file))
+             (setq file (file-name-nondirectory file))))
+         (root (file-name-sans-extension file))
+         (fspec (list (cons ?r (comint-quote-filename root))
+                      (cons ?f (comint-quote-filename file))))
+         (default (tex-compile-default fspec)))
+      (list default-directory
+          (completing-read
+           (format "Command [%s]: " (tex-summarize-command default))
+           (mapcar (lambda (x)
+                     (list (format-spec (eval (car x)) fspec)))
+                   tex-compile-commands)
+           nil nil nil 'tex-compile-history default))))
+   (save-some-buffers (not compilation-ask-about-save) nil)
+   (if (tex-shell-running)
+       (tex-kill-job)
+     (tex-start-shell))
+   (tex-send-tex-command cmd dir))
  
  (defun tex-start-tex (command file &optional dir)
    "Start a TeX run, using COMMAND on FILE."
***************
*** 1844,1850 ****
  line LINE of the window, or centered if LINE is nil."
    (interactive "P")
    (let ((tex-shell (get-buffer "*tex-shell*"))
-       (old-buffer (current-buffer))
        (window))
      (if (null tex-shell)
        (message "No TeX output buffer")
--- 2136,2141 ----
***************
*** 1961,1977 ****
  (defvar tex-indent-item tex-indent-basic)
  (defvar tex-indent-item-re "\\\\\\(bib\\)?item\\>")
  
! (easy-mmode-defsyntax tex-latex-indent-syntax-table
!   '((?$ . ".")
!     (?\( . ".")
!     (?\) . "."))
!   "Syntax table used while computing indentation."
!   :copy tex-mode-syntax-table)
  
  (defun latex-indent (&optional arg)
    (if (and (eq (get-text-property (line-beginning-position) 'face)
               tex-verbatim-face))
!       (indent-relative)
      (with-syntax-table tex-latex-indent-syntax-table
        ;; TODO: Rather than ignore $, we should try to be more clever about it.
        (let ((indent
--- 2252,2269 ----
  (defvar tex-indent-item tex-indent-basic)
  (defvar tex-indent-item-re "\\\\\\(bib\\)?item\\>")
  
! (defvar tex-latex-indent-syntax-table
!   (let ((st (make-syntax-table tex-mode-syntax-table)))
!     (modify-syntax-entry ?$ "." st)
!     (modify-syntax-entry ?\( "." st)
!     (modify-syntax-entry ?\) "." st)
!     st)
!   "Syntax table used while computing indentation.")
  
  (defun latex-indent (&optional arg)
    (if (and (eq (get-text-property (line-beginning-position) 'face)
               tex-verbatim-face))
!       'noindent
      (with-syntax-table tex-latex-indent-syntax-table
        ;; TODO: Rather than ignore $, we should try to be more clever about it.
        (let ((indent
***************
*** 2058,2066 ****
--- 2350,2416 ----
                 (min (current-column) (+ tex-indent-arg col))
               (skip-syntax-forward " ")
               (current-column))))))))))
+ ;;; DocTeX support
+ 
+ (defun doctex-font-lock-^^A ()
+   (if (eq (char-after (line-beginning-position)) ?\%)
+       (progn
+       (put-text-property
+        (1- (match-beginning 1)) (match-beginning 1)
+        'syntax-table
+        (if (= (1+ (line-beginning-position)) (match-beginning 1))
+            ;; The `%' is a single-char comment, which Emacs
+            ;; 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 ">"))))
+       (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")))))
+ 
+ (defun doctex-font-lock-syntactic-face-function (state)
+   ;; Mark DocTeX documentation, which is parsed as a style A comment
+   ;; starting in column 0.
+   (if (or (nth 3 state) (nth 7 state)
+         (not (memq (char-before (nth 8 state))
+                    '(?\n nil))))
+       ;; Anything else is just as for LaTeX.
+       (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))))))
+ 
+ (defvar doctex-font-lock-keywords
+   (append tex-font-lock-keywords
+         '(("^%<[^>]*>" (0 font-lock-preprocessor-face t)))))
+ 
+ ;;;###autoload
+ (define-derived-mode doctex-mode latex-mode "DocTeX"
+   "Major mode to edit DocTeX files."
+   (setq font-lock-defaults
+       (cons (append (car font-lock-defaults) '(doctex-font-lock-keywords))
+             (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)))))
  
  (run-hooks 'tex-mode-load-hook)
  
  (provide 'tex-mode)
  
+ ;;; arch-tag: c0a680b1-63aa-4547-84b9-4193c29c0080
  ;;; tex-mode.el ends here




reply via email to

[Prev in Thread] Current Thread [Next in Thread]