693 |
(define-key map "\C-c\C-r" 'tex-region) |
(define-key map "\C-c\C-r" 'tex-region) |
694 |
(define-key map "\C-c\C-b" 'tex-buffer) |
(define-key map "\C-c\C-b" 'tex-buffer) |
695 |
(define-key map "\C-c\C-f" 'tex-file) |
(define-key map "\C-c\C-f" 'tex-file) |
696 |
|
(define-key map "\C-c\C-c" 'tex-compile) |
697 |
(define-key map "\C-c\C-i" 'tex-bibtex-file) |
(define-key map "\C-c\C-i" 'tex-bibtex-file) |
698 |
(define-key map "\C-c\C-o" 'latex-insert-block) |
(define-key map "\C-c\C-o" 'latex-insert-block) |
699 |
(define-key map "\C-c\C-e" 'latex-close-block) |
(define-key map "\C-c\C-e" 'latex-close-block) |
1525 |
|
|
1526 |
(add-hook 'kill-emacs-hook 'tex-delete-last-temp-files) |
(add-hook 'kill-emacs-hook 'tex-delete-last-temp-files) |
1527 |
|
|
1528 |
|
;; |
1529 |
|
;; Machinery to guess the command that the user wants to execute. |
1530 |
|
;; |
1531 |
|
|
1532 |
|
(defvar tex-compile-history nil) |
1533 |
|
|
1534 |
|
(defvar tex-input-files-re |
1535 |
|
(eval-when-compile |
1536 |
|
(concat "\\." (regexp-opt '("tex" "texi" "texinfo" |
1537 |
|
"bbl" "ind" "sty" "cls") t) |
1538 |
|
;; Include files with no dots (for directories). |
1539 |
|
"\\'\\|\\`[^.]+\\'"))) |
1540 |
|
|
1541 |
|
(defcustom tex-use-reftex t |
1542 |
|
"If non-nil, use RefTeX's list of files to determine what command to use." |
1543 |
|
:type 'boolean) |
1544 |
|
|
1545 |
|
(defvar tex-compile-commands |
1546 |
|
'(((concat "pdf" tex-command |
1547 |
|
" " (shell-quote-argument tex-start-commands) " %f") |
1548 |
|
t "%r.pdf") |
1549 |
|
((concat tex-command |
1550 |
|
" " (shell-quote-argument tex-start-commands) " %f") |
1551 |
|
t "%r.dvi") |
1552 |
|
("xdvi %r &" "%r.dvi") |
1553 |
|
("advi %r &" "%r.dvi") |
1554 |
|
("bibtex %r" "%r.aux" "%r.bbl") |
1555 |
|
("makeindex %r" "%r.idx" "%r.ind") |
1556 |
|
("texindex %r.??") |
1557 |
|
("dvipdfm %r" "%r.dvi" "%r.pdf") |
1558 |
|
("dvipdf %r" "%r.dvi" "%r.pdf") |
1559 |
|
("dvips %r" "%r.dvi" "%r.ps") |
1560 |
|
("gv %r.ps &" "%r.ps") |
1561 |
|
("gv %r.pdf &" "%r.pdf") |
1562 |
|
("xpdf %r.pdf &" "%r.pdf") |
1563 |
|
("lpr %r.ps" "%r.ps")) |
1564 |
|
"List of commands for `tex-compile'. |
1565 |
|
Each element should be of the form (FORMAT IN OUT) where |
1566 |
|
FORMAT is an expression that evaluates to a string that can contain |
1567 |
|
- `%r' the main file name without extension. |
1568 |
|
- `%f' the main file name. |
1569 |
|
IN can be either a string (with the same % escapes in it) indicating |
1570 |
|
the name of the input file, or t to indicate that the input is all |
1571 |
|
the TeX files of the document, or nil if we don't know. |
1572 |
|
OUT describes the output file and is either a %-escaped string |
1573 |
|
or nil to indicate that there is no output file.") |
1574 |
|
|
1575 |
(defun tex-guess-main-file (&optional all) |
(defun tex-guess-main-file (&optional all) |
1576 |
"Find a likely `tex-main-file'. |
"Find a likely `tex-main-file'. |
1577 |
Looks for hints in other buffers in the same directory or in |
Looks for hints in other buffers in the same directory or in |
1622 |
buffer-file-name))))))) |
buffer-file-name))))))) |
1623 |
(if (file-exists-p file) file (concat file ".tex")))) |
(if (file-exists-p file) file (concat file ".tex")))) |
1624 |
|
|
1625 |
|
(defun tex-summarize-command (cmd) |
1626 |
|
(if (not (stringp cmd)) "" |
1627 |
|
(mapconcat 'identity |
1628 |
|
(mapcar (lambda (s) (car (split-string s))) |
1629 |
|
(split-string cmd "\\s-*\\(?:;\\|&&\\)\\s-*")) |
1630 |
|
"&"))) |
1631 |
|
|
1632 |
|
(defun tex-uptodate-p (file) |
1633 |
|
"Return non-nil if FILE is not uptodate w.r.t the document source files. |
1634 |
|
FILE is typically the output DVI or PDF file." |
1635 |
|
;; We should check all the files included !!! |
1636 |
|
(and |
1637 |
|
;; Clearly, the target must exist. |
1638 |
|
(file-exists-p file) |
1639 |
|
;; And the last run must not have asked for a rerun. |
1640 |
|
;; FIXME: this should check that the last run was done on the same file. |
1641 |
|
(let ((buf (condition-case nil (tex-shell-buf) (error nil)))) |
1642 |
|
(when buf |
1643 |
|
(with-current-buffer buf |
1644 |
|
(save-excursion |
1645 |
|
(goto-char (point-max)) |
1646 |
|
(and (re-search-backward |
1647 |
|
"(see the transcript file for additional information)" nil t) |
1648 |
|
(> (save-excursion |
1649 |
|
(or (re-search-backward "\\[[0-9]+\\]" nil t) |
1650 |
|
(point-min))) |
1651 |
|
(save-excursion |
1652 |
|
(or (re-search-backward "Rerun" nil t) |
1653 |
|
(point-min))))))))) |
1654 |
|
;; And the input files must not have been changed in the meantime. |
1655 |
|
(let ((files (if (and tex-use-reftex |
1656 |
|
(fboundp 'reftex-scanning-info-available-p) |
1657 |
|
(reftex-scanning-info-available-p)) |
1658 |
|
(reftex-all-document-files) |
1659 |
|
(list (file-name-directory (expand-file-name file))))) |
1660 |
|
(ignored-dirs-re |
1661 |
|
(concat |
1662 |
|
(regexp-opt |
1663 |
|
(delq nil (mapcar (lambda (s) (if (eq (aref s (1- (length s))) ?/) |
1664 |
|
(substring s 0 (1- (length s))))) |
1665 |
|
completion-ignored-extensions)) |
1666 |
|
t) "\\'")) |
1667 |
|
(uptodate t)) |
1668 |
|
(while (and files uptodate) |
1669 |
|
(let ((f (pop files))) |
1670 |
|
(if (file-directory-p f) |
1671 |
|
(unless (string-match ignored-dirs-re f) |
1672 |
|
(setq files (nconc |
1673 |
|
(directory-files f t tex-input-files-re) |
1674 |
|
files))) |
1675 |
|
(when (file-newer-than-file-p f file) |
1676 |
|
(setq uptodate nil))))) |
1677 |
|
uptodate))) |
1678 |
|
|
1679 |
|
|
1680 |
|
(autoload 'format-spec "format-spec") |
1681 |
|
|
1682 |
|
(defvar tex-executable-cache nil) |
1683 |
|
(defun tex-executable-exists-p (name) |
1684 |
|
"Like `executable-find' but with a cache." |
1685 |
|
(let ((cache (assoc name tex-executable-cache))) |
1686 |
|
(if cache (cdr cache) |
1687 |
|
(let ((executable (executable-find name))) |
1688 |
|
(push (cons name executable) tex-executable-cache) |
1689 |
|
executable)))) |
1690 |
|
|
1691 |
|
(defun tex-command-executable (cmd) |
1692 |
|
(let ((s (if (stringp cmd) cmd (eval (car cmd))))) |
1693 |
|
(substring s 0 (string-match "[ \t]\\|\\'" s)))) |
1694 |
|
|
1695 |
|
(defun tex-command-active-p (cmd fspec) |
1696 |
|
"Return non-nil if the CMD spec might need to be run." |
1697 |
|
(let ((in (nth 1 cmd)) |
1698 |
|
(out (nth 2 cmd))) |
1699 |
|
(if (stringp in) |
1700 |
|
(let ((file (format-spec in fspec))) |
1701 |
|
(when (file-exists-p file) |
1702 |
|
(or (not out) |
1703 |
|
(file-newer-than-file-p |
1704 |
|
file (format-spec out fspec))))) |
1705 |
|
(when (and (eq in t) (stringp out)) |
1706 |
|
(not (tex-uptodate-p (format-spec out fspec))))))) |
1707 |
|
|
1708 |
|
(defun tex-compile-default (dir fspec) |
1709 |
|
"Guess a default command in DIR given the format-spec FSPEC." |
1710 |
|
;; TODO: Learn to do latex+dvips! |
1711 |
|
(let ((cmds nil) |
1712 |
|
(unchanged-in nil)) |
1713 |
|
;; Only consider active commands. |
1714 |
|
(dolist (cmd tex-compile-commands) |
1715 |
|
(when (tex-executable-exists-p (tex-command-executable cmd)) |
1716 |
|
(if (tex-command-active-p cmd fspec) |
1717 |
|
(push cmd cmds) |
1718 |
|
(push (nth 1 cmd) unchanged-in)))) |
1719 |
|
;; Remove those commands whose input was considered stable for |
1720 |
|
;; some other command (typically if (t . "%.pdf") is inactive |
1721 |
|
;; then we're using pdflatex and the fact that the dvi file |
1722 |
|
;; is inexistent doesn't matter). |
1723 |
|
(let ((tmp nil)) |
1724 |
|
(dolist (cmd cmds) |
1725 |
|
(unless (member (nth 1 cmd) unchanged-in) |
1726 |
|
(push cmd tmp))) |
1727 |
|
(if tmp (setq cmds tmp))) |
1728 |
|
;; remove commands whose input is not uptodate either. |
1729 |
|
(let ((outs (delq nil (mapcar (lambda (x) (nth 2 x)) cmds)))) |
1730 |
|
(dolist (cmd (prog1 cmds (setq cmds nil))) |
1731 |
|
(unless (member (nth 1 cmd) outs) |
1732 |
|
(push cmd cmds)))) |
1733 |
|
;; Select which file we're going to operate on (the latest). |
1734 |
|
(let ((latest (nth 1 (car cmds)))) |
1735 |
|
(dolist (cmd (prog1 (cdr cmds) (setq cmds (list (car cmds))))) |
1736 |
|
(if (equal latest (nth 1 cmd)) |
1737 |
|
(push cmd cmds) |
1738 |
|
(unless (eq latest t) ;Can't beat that! |
1739 |
|
(if (or (not (stringp latest)) |
1740 |
|
(eq (nth 1 cmd) t) |
1741 |
|
(and (stringp (nth 1 cmd)) |
1742 |
|
(file-newer-than-file-p |
1743 |
|
(format-spec (nth 1 cmd) fspec) |
1744 |
|
(format-spec latest fspec)))) |
1745 |
|
(setq latest (nth 1 cmd) cmds (list cmd))))))) |
1746 |
|
;; Expand the command spec into the actual text. |
1747 |
|
(dolist (cmd (prog1 cmds (setq cmds nil))) |
1748 |
|
(push (cons (eval (car cmd)) (cdr cmd)) cmds)) |
1749 |
|
;; Select the favorite command from the history. |
1750 |
|
(let ((hist tex-compile-history) |
1751 |
|
re) |
1752 |
|
(while hist |
1753 |
|
(setq re (concat "\\`" |
1754 |
|
(regexp-quote (tex-command-executable (pop hist))) |
1755 |
|
"\\([ \t]\\|\\'\\)")) |
1756 |
|
(dolist (cmd cmds) |
1757 |
|
(if (string-match re (car cmd)) |
1758 |
|
(setq hist nil cmds (list cmd)))))) |
1759 |
|
;; Substitute and return. |
1760 |
|
(format-spec (caar cmds) fspec))) |
1761 |
|
|
1762 |
|
(defun tex-compile (dir cmd) |
1763 |
|
"Run a command CMD on current TeX buffer's file in DIR." |
1764 |
|
;; FIXME: Use time-stamps on files to decide the next op. |
1765 |
|
(interactive |
1766 |
|
(let* ((file (tex-main-file)) |
1767 |
|
(root (file-name-sans-extension file)) |
1768 |
|
(dir (file-name-directory (expand-file-name file))) |
1769 |
|
(fspec (list (cons ?r (comint-quote-filename root)) |
1770 |
|
(cons ?f (comint-quote-filename file)))) |
1771 |
|
(default (tex-compile-default dir fspec))) |
1772 |
|
(list dir |
1773 |
|
(completing-read |
1774 |
|
(format "Command [%s]: " (tex-summarize-command default)) |
1775 |
|
(mapcar (lambda (x) |
1776 |
|
(list (format-spec (eval (car x)) fspec))) |
1777 |
|
tex-compile-commands) |
1778 |
|
nil nil nil 'tex-compile-history default)))) |
1779 |
|
(save-some-buffers (not compilation-ask-about-save) nil) |
1780 |
|
(if (tex-shell-running) |
1781 |
|
(tex-kill-job) |
1782 |
|
(tex-start-shell)) |
1783 |
|
(tex-send-tex-command cmd dir)) |
1784 |
|
|
1785 |
(defun tex-start-tex (command file &optional dir) |
(defun tex-start-tex (command file &optional dir) |
1786 |
"Start a TeX run, using COMMAND on FILE." |
"Start a TeX run, using COMMAND on FILE." |