[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] Changes to emacs/lisp/textmodes/tex-mode.el [lexbind],
Miles Bader <=