comparison lisp/textmodes/tex-mode.el @ 51336:c1252b2b2582

(latex-block-args-alist, latex-block-body-alist): New vars. (latex-insert-block): Use them. (tex-string-prefix-p): New fun. (tex-guess-main-file): Use it to detect when the main file is in a parent directory. (tex-main-file): Try to find a main-file in parent directories. (tex-compile-default): Don't use `gv' on pdf files just because `gv' was used recently on a ps file. Remove unused arg `dir'. Reuse a previous command as-is if it applied to the same file. (tex-compile): Use the right file name when file is not in dir.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Fri, 30 May 2003 18:52:46 +0000
parents aeb075459c1d
children ebea7b586362
comparison
equal deleted inserted replaced
51335:816e3b31173a 51336:c1252b2b2582
1210 (setq inside t))) 1210 (setq inside t)))
1211 inside)))) 1211 inside))))
1212 1212
1213 (defvar latex-block-default "enumerate") 1213 (defvar latex-block-default "enumerate")
1214 1214
1215 (defvar latex-block-args-alist
1216 '(("array" nil ?\{ (skeleton-read "[options]: ") ?\})
1217 ("tabular" nil ?\{ (skeleton-read "[options]: ") ?\}))
1218 "Skeleton element to use for arguments to particular environments.
1219 Every element of the list has the form (NAME . SKEL-ELEM) where NAME is
1220 the name of the environment and SKEL-ELEM is an element to use in
1221 a skeleton (see `skeleton-insert').")
1222
1223 (defvar latex-block-body-alist
1224 '(("enumerate" nil '(latex-insert-item) > _)
1225 ("itemize" nil '(latex-insert-item) > _)
1226 ("table" nil "\\caption{" > - "}" > \n _)
1227 ("figure" nil > _ \n "\\caption{" > _ "}" >))
1228 "Skeleton element to use for the body of particular environments.
1229 Every element of the list has the form (NAME . SKEL-ELEM) where NAME is
1230 the name of the environment and SKEL-ELEM is an element to use in
1231 a skeleton (see `skeleton-insert').")
1232
1215 ;; Like tex-insert-braces, but for LaTeX. 1233 ;; Like tex-insert-braces, but for LaTeX.
1216 (defalias 'tex-latex-block 'latex-insert-block) 1234 (defalias 'tex-latex-block 'latex-insert-block)
1217 (define-skeleton latex-insert-block 1235 (define-skeleton latex-insert-block
1218 "Create a matching pair of lines \\begin[OPT]{NAME} and \\end{NAME} at point. 1236 "Create a matching pair of lines \\begin[OPT]{NAME} and \\end{NAME} at point.
1219 Puts point on a blank line between them." 1237 Puts point on a blank line between them."
1227 (member choice latex-block-names)) 1245 (member choice latex-block-names))
1228 ;; Remember new block names for later completion. 1246 ;; Remember new block names for later completion.
1229 (push choice latex-block-names)) 1247 (push choice latex-block-names))
1230 choice) 1248 choice)
1231 \n "\\begin{" str "}" 1249 \n "\\begin{" str "}"
1232 ?\[ (skeleton-read "[options]: ") & ?\] | -1 1250 (cdr (assoc str latex-block-args-alist))
1233 > \n _ \n 1251 > \n (or (cdr (assoc str latex-block-body-alist)) '(nil > _)) \n
1234 "\\end{" str "}" > \n) 1252 "\\end{" str "}" > \n)
1235 1253
1236 (define-skeleton latex-insert-item 1254 (define-skeleton latex-insert-item
1237 "Insert a \item macro." 1255 "Insert a \item macro."
1238 nil 1256 nil
1570 the name of the input file, or t to indicate that the input is all 1588 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. 1589 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 1590 OUT describes the output file and is either a %-escaped string
1573 or nil to indicate that there is no output file.") 1591 or nil to indicate that there is no output file.")
1574 1592
1593 ;; defsubst* gives better byte-code than defsubst.
1594 (defsubst* tex-string-prefix-p (str1 str2)
1595 "Return non-nil if STR1 is a prefix of STR2"
1596 (eq t (compare-strings str2 nil (length str1) str1 nil nil)))
1597
1575 (defun tex-guess-main-file (&optional all) 1598 (defun tex-guess-main-file (&optional all)
1576 "Find a likely `tex-main-file'. 1599 "Find a likely `tex-main-file'.
1577 Looks for hints in other buffers in the same directory or in 1600 Looks for hints in other buffers in the same directory or in
1578 ALL other buffers." 1601 ALL other buffers. If ALL is `sub' only look at buffers in parent directories
1602 of the current buffer."
1579 (let ((dir default-directory) 1603 (let ((dir default-directory)
1580 (header-re tex-start-of-header)) 1604 (header-re tex-start-of-header))
1581 (catch 'found 1605 (catch 'found
1582 ;; Look for a buffer with `tex-main-file' set. 1606 ;; Look for a buffer with `tex-main-file' set.
1583 (dolist (buf (if (consp all) all (buffer-list))) 1607 (dolist (buf (if (consp all) all (buffer-list)))
1584 (with-current-buffer buf 1608 (with-current-buffer buf
1585 (when (and (or all (equal dir default-directory)) 1609 (when (and (cond
1610 ((null all) (equal dir default-directory))
1611 ((eq all 'sub) (tex-string-prefix-p default-directory dir))
1612 (t))
1586 (stringp tex-main-file)) 1613 (stringp tex-main-file))
1587 (throw 'found (expand-file-name tex-main-file))))) 1614 (throw 'found (expand-file-name tex-main-file)))))
1588 ;; Look for a buffer containing the magic `tex-start-of-header'. 1615 ;; Look for a buffer containing the magic `tex-start-of-header'.
1589 (dolist (buf (if (consp all) all (buffer-list))) 1616 (dolist (buf (if (consp all) all (buffer-list)))
1590 (with-current-buffer buf 1617 (with-current-buffer buf
1591 (when (and (or all (equal dir default-directory)) 1618 (when (and (cond
1619 ((null all) (equal dir default-directory))
1620 ((eq all 'sub) (tex-string-prefix-p default-directory dir))
1621 (t))
1592 buffer-file-name 1622 buffer-file-name
1593 ;; (or (easy-mmode-derived-mode-p 'latex-mode) 1623 ;; (or (easy-mmode-derived-mode-p 'latex-mode)
1594 ;; (easy-mmode-derived-mode-p 'plain-tex-mode)) 1624 ;; (easy-mmode-derived-mode-p 'plain-tex-mode))
1595 (save-excursion 1625 (save-excursion
1596 (save-restriction 1626 (save-restriction
1616 (+ (point) 10000) t)) 1646 (+ (point) 10000) t))
1617 ;; This is the main file. 1647 ;; This is the main file.
1618 buffer-file-name 1648 buffer-file-name
1619 ;; This isn't the main file, let's try to find better, 1649 ;; This isn't the main file, let's try to find better,
1620 (or (tex-guess-main-file) 1650 (or (tex-guess-main-file)
1651 (tex-guess-main-file 'sub)
1621 ;; (tex-guess-main-file t) 1652 ;; (tex-guess-main-file t)
1622 buffer-file-name))))))) 1653 buffer-file-name)))))))
1623 (if (file-exists-p file) file (concat file ".tex")))) 1654 (if (file-exists-p file) file (concat file ".tex"))))
1624 1655
1625 (defun tex-summarize-command (cmd) 1656 (defun tex-summarize-command (cmd)
1703 (file-newer-than-file-p 1734 (file-newer-than-file-p
1704 file (format-spec out fspec))))) 1735 file (format-spec out fspec)))))
1705 (when (and (eq in t) (stringp out)) 1736 (when (and (eq in t) (stringp out))
1706 (not (tex-uptodate-p (format-spec out fspec))))))) 1737 (not (tex-uptodate-p (format-spec out fspec)))))))
1707 1738
1708 (defun tex-compile-default (dir fspec) 1739 (defun tex-compile-default (fspec)
1709 "Guess a default command in DIR given the format-spec FSPEC." 1740 "Guess a default command given the format-spec FSPEC."
1710 ;; TODO: Learn to do latex+dvips! 1741 ;; TODO: Learn to do latex+dvips!
1711 (let ((cmds nil) 1742 (let ((cmds nil)
1712 (unchanged-in nil)) 1743 (unchanged-in nil))
1713 ;; Only consider active commands. 1744 ;; Only consider active commands.
1714 (dolist (cmd tex-compile-commands) 1745 (dolist (cmd tex-compile-commands)
1722 ;; is inexistent doesn't matter). 1753 ;; is inexistent doesn't matter).
1723 (let ((tmp nil)) 1754 (let ((tmp nil))
1724 (dolist (cmd cmds) 1755 (dolist (cmd cmds)
1725 (unless (member (nth 1 cmd) unchanged-in) 1756 (unless (member (nth 1 cmd) unchanged-in)
1726 (push cmd tmp))) 1757 (push cmd tmp)))
1758 ;; Only remove if there's something left.
1727 (if tmp (setq cmds tmp))) 1759 (if tmp (setq cmds tmp)))
1728 ;; remove commands whose input is not uptodate either. 1760 ;; Remove commands whose input is not uptodate either.
1729 (let ((outs (delq nil (mapcar (lambda (x) (nth 2 x)) cmds)))) 1761 (let ((outs (delq nil (mapcar (lambda (x) (nth 2 x)) cmds)))
1730 (dolist (cmd (prog1 cmds (setq cmds nil))) 1762 (tmp nil))
1763 (dolist (cmd cmds)
1731 (unless (member (nth 1 cmd) outs) 1764 (unless (member (nth 1 cmd) outs)
1732 (push cmd cmds)))) 1765 (push cmd tmp)))
1766 ;; Only remove if there's something left.
1767 (if tmp (setq cmds tmp)))
1733 ;; Select which file we're going to operate on (the latest). 1768 ;; Select which file we're going to operate on (the latest).
1734 (let ((latest (nth 1 (car cmds)))) 1769 (let ((latest (nth 1 (car cmds))))
1735 (dolist (cmd (prog1 (cdr cmds) (setq cmds (list (car cmds))))) 1770 (dolist (cmd (prog1 (cdr cmds) (setq cmds (list (car cmds)))))
1736 (if (equal latest (nth 1 cmd)) 1771 (if (equal latest (nth 1 cmd))
1737 (push cmd cmds) 1772 (push cmd cmds)
1746 ;; Expand the command spec into the actual text. 1781 ;; Expand the command spec into the actual text.
1747 (dolist (cmd (prog1 cmds (setq cmds nil))) 1782 (dolist (cmd (prog1 cmds (setq cmds nil)))
1748 (push (cons (eval (car cmd)) (cdr cmd)) cmds)) 1783 (push (cons (eval (car cmd)) (cdr cmd)) cmds))
1749 ;; Select the favorite command from the history. 1784 ;; Select the favorite command from the history.
1750 (let ((hist tex-compile-history) 1785 (let ((hist tex-compile-history)
1751 re) 1786 re hist-cmd)
1752 (while hist 1787 (while hist
1788 (setq hist-cmd (pop hist))
1753 (setq re (concat "\\`" 1789 (setq re (concat "\\`"
1754 (regexp-quote (tex-command-executable (pop hist))) 1790 (regexp-quote (tex-command-executable hist-cmd))
1755 "\\([ \t]\\|\\'\\)")) 1791 "\\([ \t]\\|\\'\\)"))
1756 (dolist (cmd cmds) 1792 (dolist (cmd cmds)
1757 (if (string-match re (car cmd)) 1793 ;; If the hist entry uses the same command and applies to a file
1758 (setq hist nil cmds (list cmd)))))) 1794 ;; of the same type (e.g. `gv %r.pdf' vs `gv %r.ps'), select cmd.
1759 ;; Substitute and return. 1795 (and (string-match re (car cmd))
1760 (format-spec (caar cmds) fspec))) 1796 (or (not (string-match "%[fr]\\([-._[:alnum:]]+\\)" (car cmd)))
1797 (string-match (regexp-quote (match-string 1 (car cmd)))
1798 hist-cmd))
1799 (setq hist nil cmds (list cmd)))))
1800 ;; Substitute and return.
1801 (if (and hist-cmd
1802 (string-match (concat "[' \t\"]" (format-spec "%r" fspec)
1803 "\\([;&' \t\"]\\|\\'\\)") hist-cmd))
1804 ;; The history command was already applied to the same file,
1805 ;; so just reuse it.
1806 hist-cmd
1807 (if cmds (format-spec (caar cmds) fspec))))))
1761 1808
1762 (defun tex-compile (dir cmd) 1809 (defun tex-compile (dir cmd)
1763 "Run a command CMD on current TeX buffer's file in DIR." 1810 "Run a command CMD on current TeX buffer's file in DIR."
1764 ;; FIXME: Use time-stamps on files to decide the next op. 1811 ;; FIXME: Use time-stamps on files to decide the next op.
1765 (interactive 1812 (interactive
1766 (let* ((file (tex-main-file)) 1813 (let* ((file (tex-main-file))
1814 (dir (prog1 (file-name-directory (expand-file-name file))
1815 (setq file (file-name-nondirectory file))))
1767 (root (file-name-sans-extension file)) 1816 (root (file-name-sans-extension file))
1768 (dir (file-name-directory (expand-file-name file)))
1769 (fspec (list (cons ?r (comint-quote-filename root)) 1817 (fspec (list (cons ?r (comint-quote-filename root))
1770 (cons ?f (comint-quote-filename file)))) 1818 (cons ?f (comint-quote-filename file))))
1771 (default (tex-compile-default dir fspec))) 1819 (default (tex-compile-default fspec)))
1772 (list dir 1820 (list dir
1773 (completing-read 1821 (completing-read
1774 (format "Command [%s]: " (tex-summarize-command default)) 1822 (format "Command [%s]: " (tex-summarize-command default))
1775 (mapcar (lambda (x) 1823 (mapcar (lambda (x)
1776 (list (format-spec (eval (car x)) fspec))) 1824 (list (format-spec (eval (car x)) fspec)))