tex-mode.el 52.8 KB
Newer Older
Eric S. Raymond's avatar
Eric S. Raymond committed
1 2
;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands.

3
;; Copyright (C) 1985, 86, 89, 92, 94, 95, 96, 97, 98, 1999
4
;;       Free Software Foundation, Inc.
Eric S. Raymond's avatar
Eric S. Raymond committed
5

Richard M. Stallman's avatar
Richard M. Stallman committed
6
;; Maintainer: FSF
Eric S. Raymond's avatar
Eric S. Raymond committed
7
;; Keywords: tex
Eric S. Raymond's avatar
Eric S. Raymond committed
8

9
;; Contributions over the years by William F. Schelter, Dick King,
Richard M. Stallman's avatar
Richard M. Stallman committed
10
;; Stephen Gildea, Michael Prange, Jacob Gore, and Edward M. Reingold.
11

root's avatar
root committed
12 13 14 15
;; This file is part of GNU Emacs.

;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
Eric S. Raymond's avatar
Eric S. Raymond committed
16
;; the Free Software Foundation; either version 2, or (at your option)
root's avatar
root committed
17 18 19 20 21 22 23 24
;; any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
25 26 27
;; along with GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
root's avatar
root committed
28

Eric S. Raymond's avatar
Eric S. Raymond committed
29 30
;;; Code:

31 32 33 34 35
;; Pacify the byte-compiler
(eval-when-compile
  (require 'compare-w)
  (require 'skeleton))

36
(require 'shell)
37
(require 'compile)
38

39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
(defgroup tex-file nil
  "TeX files and directories"
  :prefix "tex-"
  :group 'tex)

(defgroup tex-run nil
  "Running external commands from TeX mode"
  :prefix "tex-"
  :group 'tex)

(defgroup tex-view nil
  "Viewing and printing TeX files"
  :prefix "tex-"
  :group 'tex)

Jim Blandy's avatar
Jim Blandy committed
54
;;;###autoload
55 56 57 58 59
(defcustom tex-shell-file-name nil
  "*If non-nil, the shell file name to run in the subshell used to run TeX."
  :type '(choice (const :tag "None" nil)
		 string)
  :group 'tex-run)
60

Jim Blandy's avatar
Jim Blandy committed
61
;;;###autoload
62
(defcustom tex-directory "."
63
  "*Directory in which temporary files are written.
Richard M. Stallman's avatar
Richard M. Stallman committed
64
You can make this `/tmp' if your TEXINPUTS has no relative directories in it
65
and you don't try to apply \\[tex-region] or \\[tex-buffer] when there are
66 67 68
`\\input' commands with relative directories."
  :type 'directory
  :group 'tex-file)
root's avatar
root committed
69

70
;;;###autoload
71
(defcustom tex-first-line-header-regexp nil
72 73 74
  "Regexp for matching a first line which `tex-region' should include.
If this is non-nil, it should be a regular expression string;
if it matches the first line of the file,
75 76 77 78
`tex-region' always includes the first line in the TeX run."
  :type '(choice (const :tag "None" nil)
                 regexp)
  :group 'tex-file)
79

80
;;;###autoload
81
(defcustom tex-main-file nil
82
  "*The main TeX source file which includes this buffer's file.
83 84
The command `tex-file' runs TeX on the file specified by `tex-main-file'
if the variable is non-nil."
85 86 87
  :type '(choice (const :tag "None" nil)
                 file)
  :group 'tex-file)
88

Jim Blandy's avatar
Jim Blandy committed
89
;;;###autoload
90 91 92 93
(defcustom tex-offer-save t
  "*If non-nil, ask about saving modified buffers before \\[tex-file] is run."
  :type 'boolean
  :group 'tex-file)
root's avatar
root committed
94

Jim Blandy's avatar
Jim Blandy committed
95
;;;###autoload
96
(defcustom tex-run-command "tex"
root's avatar
root committed
97
  "*Command used to run TeX subjob.
98 99
TeX Mode sets `tex-command' to this string.
See the documentation of that variable."
100 101
  :type 'string
  :group 'tex-run)
root's avatar
root committed
102

Jim Blandy's avatar
Jim Blandy committed
103
;;;###autoload
104
(defcustom latex-run-command "latex"
root's avatar
root committed
105
  "*Command used to run LaTeX subjob.
106 107
LaTeX Mode sets `tex-command' to this string.
See the documentation of that variable."
108 109
  :type 'string
  :group 'tex-run)
110

111 112 113
;;;###autoload
(defcustom slitex-run-command "slitex"
  "*Command used to run SliTeX subjob.
114 115
SliTeX Mode sets `tex-command' to this string.
See the documentation of that variable."
116 117 118
  :type 'string
  :group 'tex-run)

119 120
;;;###autoload
(defcustom tex-start-options-string "\\nonstopmode\\input"
121
  "*TeX options to use when running TeX.
122 123 124 125 126 127
These precede the input file name. If nil, TeX runs without option.
See the documentation of `tex-command'."
  :type '(radio (const :tag "Interactive \(nil\)" nil)
		(const :tag "Nonstop \(\"\\nonstopmode\\input\"\)"
		       "\\nonstopmode\\input")
		(string :tag "String at your choice"))
128 129 130
  :group 'tex-run
  :version "20.4")

131
(defvar standard-latex-block-names
132 133 134 135 136 137 138 139 140
  '("abstract"         "array"            "center"       "description"
    "displaymath"      "document"         "enumerate"    "eqnarray"
    "eqnarray*"        "equation"         "figure"       "figure*"
    "flushleft"        "flushright"       "itemize"      "letter"
    "list"             "minipage"         "picture"      "quotation"
    "quote"            "slide"            "sloppypar"    "tabbing"
    "table"            "table*"           "tabular"      "tabular*"
    "thebibliography"  "theindex*"        "titlepage"    "trivlist"
    "verbatim"         "verbatim*"        "verse")
141 142
  "Standard LaTeX block names.")

Jim Blandy's avatar
Jim Blandy committed
143
;;;###autoload
144
(defcustom latex-block-names nil
145
  "*User defined LaTeX block names.
146 147 148
Combined with `standard-latex-block-names' for minibuffer completion."
  :type '(repeat string)
  :group 'tex-run)
root's avatar
root committed
149

Jim Blandy's avatar
Jim Blandy committed
150
;;;###autoload
151
(defcustom tex-bibtex-command "bibtex"
152
  "*Command used by `tex-bibtex-file' to gather bibliographic data.
Richard M. Stallman's avatar
Richard M. Stallman committed
153
If this string contains an asterisk (`*'), that is replaced by the file name;
154 155 156
otherwise, the file name, preceded by blank, is added at the end."
  :type 'string
  :group 'tex-run)
root's avatar
root committed
157

Jim Blandy's avatar
Jim Blandy committed
158
;;;###autoload
159
(defcustom tex-dvi-print-command "lpr -d"
160
  "*Command used by \\[tex-print] to print a .dvi file.
Richard M. Stallman's avatar
Richard M. Stallman committed
161
If this string contains an asterisk (`*'), that is replaced by the file name;
162 163 164
otherwise, the file name, preceded by blank, is added at the end."
  :type 'string
  :group 'tex-view)
165

Jim Blandy's avatar
Jim Blandy committed
166
;;;###autoload
167
(defcustom tex-alt-dvi-print-command "lpr -d"
168
  "*Command used by \\[tex-print] with a prefix arg to print a .dvi file.
Richard M. Stallman's avatar
Richard M. Stallman committed
169 170
If this string contains an asterisk (`*'), that is replaced by the file name;
otherwise, the file name, preceded by blank, is added at the end.
171

Richard M. Stallman's avatar
Richard M. Stallman committed
172 173
If two printers are not enough of a choice, you can set the variable
`tex-alt-dvi-print-command' to an expression that asks what you want;
174 175 176 177 178 179
for example,

    (setq tex-alt-dvi-print-command
         '(format \"lpr -P%s\" (read-string \"Use printer: \")))

would tell \\[tex-print] with a prefix argument to ask you which printer to
180 181 182 183
use."
  :type '(choice (string :tag "Command")
		 (sexp :tag "Expression"))
  :group 'tex-view)
root's avatar
root committed
184

Jim Blandy's avatar
Jim Blandy committed
185
;;;###autoload
186
(defcustom tex-dvi-view-command nil
Richard M. Stallman's avatar
Richard M. Stallman committed
187 188 189
  "*Command used by \\[tex-view] to display a `.dvi' file.
If this string contains an asterisk (`*'), that is replaced by the file name;
otherwise, the file name, preceded by blank, is added at the end.
190 191 192 193 194 195 196

This can be set conditionally so that the previewer used is suitable for the
window system being used.  For example,

    (setq tex-dvi-view-command
          (if (eq window-system 'x) \"xdvi\" \"dvi2tty * | cat -s\"))

Richard M. Stallman's avatar
Richard M. Stallman committed
197
would tell \\[tex-view] to use xdvi under X windows and to use dvi2tty
198 199 200
otherwise."
  :type '(choice (const nil) string)
  :group 'tex-view)
root's avatar
root committed
201

Jim Blandy's avatar
Jim Blandy committed
202
;;;###autoload
203
(defcustom tex-show-queue-command "lpq"
204
  "*Command used by \\[tex-show-print-queue] to show the print queue.
205 206 207
Should show the queue(s) that \\[tex-print] puts jobs on."
  :type 'string
  :group 'tex-view)
root's avatar
root committed
208

Jim Blandy's avatar
Jim Blandy committed
209
;;;###autoload
210
(defcustom tex-default-mode 'latex-mode
root's avatar
root committed
211 212 213
  "*Mode to enter for a new file that might be either TeX or LaTeX.
This variable is used when it can't be determined whether the file
is plain TeX or LaTeX or what because the file contains no commands.
214 215 216
Normally set to either `plain-tex-mode' or `latex-mode'."
  :type 'function
  :group 'tex)
root's avatar
root committed
217

Jim Blandy's avatar
Jim Blandy committed
218
;;;###autoload
219 220 221 222
(defcustom tex-open-quote "``"
  "*String inserted by typing \\[tex-insert-quote] to open a quotation."
  :type 'string
  :group 'tex)
root's avatar
root committed
223

Jim Blandy's avatar
Jim Blandy committed
224
;;;###autoload
225 226 227 228
(defcustom tex-close-quote "''"
  "*String inserted by typing \\[tex-insert-quote] to close a quotation."
  :type 'string
  :group 'tex)
root's avatar
root committed
229

230 231 232
(defvar tex-last-temp-file nil
  "Latest temporary file generated by \\[tex-region] and \\[tex-buffer].
Deleted when the \\[tex-region] or \\[tex-buffer] is next run, or when the
Richard M. Stallman's avatar
Richard M. Stallman committed
233
tex shell terminates.")
234

root's avatar
root committed
235
(defvar tex-command nil
236 237 238 239 240 241 242 243
  "*Command to run TeX.
If this string contains an asterisk \(`*'\), that is replaced by the file name\;
otherwise the \(shell-quoted\) value of `tex-start-options-string' and
the file name are added at the end, with blanks as separators.

In TeX, LaTeX, and SliTeX Mode this variable becomes buffer local.
In these modes, use \\[set-variable] if you want to change it for the
current buffer.")
root's avatar
root committed
244 245 246 247 248

(defvar tex-trailer nil
  "String appended after the end of a region sent to TeX by \\[tex-region].")

(defvar tex-start-of-header nil
249
  "Regular expression used by \\[tex-region] to find start of file's header.")
root's avatar
root committed
250 251

(defvar tex-end-of-header nil
252
  "Regular expression used by \\[tex-region] to find end of file's header.")
root's avatar
root committed
253 254 255

(defvar tex-shell-cd-command "cd"
  "Command to give to shell running TeX to change directory.
Richard M. Stallman's avatar
Richard M. Stallman committed
256
The value of `tex-directory' is appended to this, separated by a space.")
root's avatar
root committed
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

(defvar tex-zap-file nil
  "Temporary file name used for text being sent as input to TeX.
Should be a simple file name with no extension or directory specification.")

(defvar tex-last-buffer-texed nil
  "Buffer which was last TeXed.")

(defvar tex-print-file nil
  "File name that \\[tex-print] prints.
Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].")

(defvar tex-mode-syntax-table nil
  "Syntax table used while in TeX mode.")

272
(defcustom latex-imenu-indent-string ". "
273 274 275 276 277
  "*String to add repeated in front of nested sectional units for Imenu.
An alternative value is \" . \", if you use a font with a narrow period."
  :type 'string
  :group 'tex)

278 279 280 281 282 283
(defvar latex-section-alist
  '(("part" . 0) ("chapter" . 1)
    ("section" . 2) ("subsection" . 3)
    ("subsubsection" . 4)
    ("paragraph" . 5) ("subparagraph" . 6)))

284 285
(defun latex-imenu-create-index ()
  "Generates an alist for imenu from a LaTeX buffer."
286 287 288 289 290 291 292 293 294 295 296 297 298 299
  (let (i0 menu case-fold-search)
    (save-excursion
      ;; Find the top-most level in this file but don't allow it to be
      ;; any deeper than "section" (which is top-level in an article).
      (goto-char (point-min))
      (if (search-forward-regexp "\\\\part\\*?[ \t]*{" nil t)
	  (setq i0 0)
	(if (search-forward-regexp "\\\\chapter\\*?[ \t]*{" nil t)
	    (setq i0 1)
	  (setq i0 2)))

      ;; Look for chapters and sections.
      (goto-char (point-min))
      (while (search-forward-regexp
300
	      (progn
301 302
		(concat "\\\\" (regexp-opt (mapcar 'car latex-section-alist) t)
			"\\*?[ \t]*{")) nil t)
303 304 305 306 307
	(let ((start (match-beginning 0))
	      (here (point))
	      (i (cdr (assoc (buffer-substring-no-properties
			      (match-beginning 1)
			      (match-end 1))
308
			     latex-section-alist))))
309 310 311 312 313 314
	  (backward-char 1)
	  (condition-case err
	      (progn
		;; Using sexps allows some use of matching {...} inside
		;; titles.
		(forward-sexp 1)
315 316 317 318 319 320 321 322
		(push (cons (concat (apply 'concat
					   (make-list
					    (max 0 (- i i0))
					    latex-imenu-indent-string))
				    (buffer-substring-no-properties
				     here (1- (point))))
			    start)
		      menu))
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
	    (error nil))))

      ;; Look for included material.
      (goto-char (point-min))
      (while (search-forward-regexp
	      "\\\\\\(include\\|input\\|verbatiminput\\|bibliography\\)\
[ \t]*{\\([^}\n]+\\)}"
	      nil t)
	(setq menu
	      (cons (cons (concat "<<" (buffer-substring-no-properties
					(match-beginning 2)
					(match-end 2))
				  (if (= (char-after (match-beginning 1)) ?b)
				      ".bbl"
				    ".tex"))
			  (match-beginning 0))
		    menu)))

      ;; Look for \frontmatter, \mainmatter, \backmatter, and \appendix.
      (goto-char (point-min))
      (while (search-forward-regexp
	      "\\\\\\(frontmatter\\|mainmatter\\|backmatter\\|appendix\\)\\b"
	      nil t)
	(setq menu
	      (cons (cons "--" (match-beginning 0))
		    menu)))

      ;; Sort in increasing buffer position order.
      (sort menu (function (lambda (a b) (< (cdr a) (cdr b))))))))
352

root's avatar
root committed
353
(defun tex-define-common-keys (keymap)
Richard M. Stallman's avatar
Richard M. Stallman committed
354
  "Define the keys that we want defined both in TeX mode and in the TeX shell."
root's avatar
root committed
355 356 357 358 359
  (define-key keymap "\C-c\C-k" 'tex-kill-job)
  (define-key keymap "\C-c\C-l" 'tex-recenter-output-buffer)
  (define-key keymap "\C-c\C-q" 'tex-show-print-queue)
  (define-key keymap "\C-c\C-p" 'tex-print)
  (define-key keymap "\C-c\C-v" 'tex-view)
360 361 362 363

  (define-key keymap [menu-bar tex] (cons "TeX" (make-sparse-keymap "TeX")))

  (define-key keymap [menu-bar tex tex-kill-job] '("Tex Kill" . tex-kill-job))
364 365
  (define-key keymap [menu-bar tex tex-recenter-output-buffer]
    '("Tex Recenter" . tex-recenter-output-buffer))
366 367
  (define-key keymap [menu-bar tex tex-show-print-queue]
    '("Show Print Queue" . tex-show-print-queue))
368 369
  (define-key keymap [menu-bar tex tex-alt-print]
    '("Tex Print (alt printer)" . tex-alt-print))
370
  (define-key keymap [menu-bar tex tex-print] '("Tex Print" . tex-print))
371
  (define-key keymap [menu-bar tex tex-view] '("Tex View" . tex-view))
root's avatar
root committed
372 373 374 375
  )

(defvar tex-mode-map nil "Keymap for TeX mode.")

376
(if tex-mode-map
root's avatar
root committed
377 378 379 380 381 382 383 384 385 386 387 388
    nil
  (setq tex-mode-map (make-sparse-keymap))
  (tex-define-common-keys tex-mode-map)
  (define-key tex-mode-map "\"" 'tex-insert-quote)
  (define-key tex-mode-map "\n" 'tex-terminate-paragraph)
  (define-key tex-mode-map "\C-c}" 'up-list)
  (define-key tex-mode-map "\C-c{" 'tex-insert-braces)
  (define-key tex-mode-map "\C-c\C-r" 'tex-region)
  (define-key tex-mode-map "\C-c\C-b" 'tex-buffer)
  (define-key tex-mode-map "\C-c\C-f" 'tex-file)
  (define-key tex-mode-map "\C-c\C-i" 'tex-bibtex-file)
  (define-key tex-mode-map "\C-c\C-o" 'tex-latex-block)
389
  (define-key tex-mode-map "\C-c\C-e" 'tex-close-latex-block)
390
  (define-key tex-mode-map "\C-c\C-u" 'tex-goto-last-unclosed-latex-block)
391 392
  (define-key tex-mode-map "\C-c\C-m" 'tex-feed-input)
  (define-key tex-mode-map [(control return)] 'tex-feed-input)
393 394
  (define-key tex-mode-map [menu-bar tex tex-bibtex-file]
    '("BibTeX File" . tex-bibtex-file))
395 396
  (define-key tex-mode-map [menu-bar tex tex-validate-region]
    '("Validate Region" . tex-validate-region))
397 398
  (define-key tex-mode-map [menu-bar tex tex-validate-buffer]
    '("Validate Buffer" . tex-validate-buffer))
399
  (define-key tex-mode-map [menu-bar tex tex-region]
400
    '("TeX Region" . tex-region))
401
  (define-key tex-mode-map [menu-bar tex tex-buffer]
402 403
    '("TeX Buffer" . tex-buffer))
  (define-key tex-mode-map [menu-bar tex tex-file] '("TeX File" . tex-file)))
404 405 406 407 408 409 410 411 412

(put 'tex-region 'menu-enable 'mark-active)
(put 'tex-validate-region 'menu-enable 'mark-active)
(put 'tex-print 'menu-enable '(stringp tex-print-file))
(put 'tex-alt-print 'menu-enable '(stringp tex-print-file))
(put 'tex-view 'menu-enable '(stringp tex-print-file))
(put 'tex-recenter-output-buffer 'menu-enable '(get-buffer "*tex-shell*"))
(put 'tex-kill-job 'menu-enable '(tex-shell-running))

413 414 415 416 417
(defvar tex-shell-map
  (let ((m (make-sparse-keymap)))
    (set-keymap-parent m shell-mode-map)
    (tex-define-common-keys m)
    m)
Richard M. Stallman's avatar
Richard M. Stallman committed
418
  "Keymap for the TeX shell.
419
Inherits `shell-mode-map' with a few additions.")
root's avatar
root committed
420

421 422 423 424 425 426 427 428 429 430 431 432 433
(defvar tex-face-alist
  '((bold . "{\\bf ")
    (italic . "{\\it ")
    (bold-italic . "{\\bi ")		; hypothetical
    (underline . "\\underline{")
    (default . "{\\rm "))
  "Alist of face and TeX font name for facemenu.")

(defvar tex-latex-face-alist
  `((italic . "{\\em ")
    ,@tex-face-alist)
  "Alist of face and LaTeX font name for facemenu.")

root's avatar
root committed
434 435
;;; This would be a lot simpler if we just used a regexp search,
;;; but then it would be too slow.
Roland McGrath's avatar
Roland McGrath committed
436
;;;###autoload
root's avatar
root committed
437 438 439
(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
Richard M. Stallman's avatar
Richard M. Stallman committed
440 441 442 443
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."
root's avatar
root committed
444
  (interactive)
445
  (let ((mode tex-default-mode) slash comment)
root's avatar
root committed
446 447 448 449 450 451 452 453
    (save-excursion
      (goto-char (point-min))
      (while (and (setq slash (search-forward "\\" nil t))
		  (setq comment (let ((search-end (point)))
				  (save-excursion
				    (beginning-of-line)
				    (search-forward "%" search-end t))))))
      (if (and slash (not comment))
454
	  (setq mode (if (looking-at "documentstyle\\|documentclass\\|begin\\b\\|NeedsTeXFormat{LaTeX")
455 456
                         (if (looking-at
			      "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}")
root's avatar
root committed
457 458 459
                             'slitex-mode
                           'latex-mode)
		       'plain-tex-mode))))
460
    (funcall mode)))
461

Jim Blandy's avatar
Jim Blandy committed
462
;;;###autoload
463
(defalias 'TeX-mode 'tex-mode)
Jim Blandy's avatar
Jim Blandy committed
464
;;;###autoload
465 466
(defalias 'plain-TeX-mode 'plain-tex-mode)
;;;###autoload
467
(defalias 'LaTeX-mode 'latex-mode)
root's avatar
root committed
468

Roland McGrath's avatar
Roland McGrath committed
469
;;;###autoload
470
(define-derived-mode plain-tex-mode text-mode "TeX"
root's avatar
root committed
471 472 473 474 475 476 477 478 479 480 481 482 483
  "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,
and '' when it appears to be the end; it inserts \" only after a \\.

Use \\[tex-region] to run TeX on the current region, plus a \"header\"
copied from the top of the file (containing macro definitions, etc.),
running TeX under a special subshell.  \\[tex-buffer] does the whole buffer.
\\[tex-file] saves the buffer and then processes the file.
\\[tex-print] prints the .dvi file made by any of these.
\\[tex-view] previews the .dvi file made by any of these.
\\[tex-bibtex-file] runs bibtex on the file of the current buffer.

484
Use \\[tex-validate-buffer] to check buffer for paragraphs containing
root's avatar
root committed
485 486 487 488 489 490 491 492 493 494 495 496 497
mismatched $'s or braces.

Special commands:
\\{tex-mode-map}

Mode variables:
tex-run-command
	Command string used by \\[tex-region] or \\[tex-buffer].
tex-directory
	Directory in which to create temporary files for TeX jobs
	run by \\[tex-region] or \\[tex-buffer].
tex-dvi-print-command
	Command string used by \\[tex-print] to print a .dvi file.
498 499 500
tex-alt-dvi-print-command
	Alternative command string used by \\[tex-print] (when given a prefix
	argument) to print a .dvi file.
root's avatar
root committed
501 502 503 504 505 506
tex-dvi-view-command
	Command string used by \\[tex-view] to preview a .dvi file.
tex-show-queue-command
	Command string used by \\[tex-show-print-queue] to show the print
	queue that \\[tex-print] put your job on.

Richard M. Stallman's avatar
Richard M. Stallman committed
507 508 509
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."
root's avatar
root committed
510 511
  (tex-common-initialization)
  (setq tex-command tex-run-command)
512 513
  (setq tex-start-of-header "%\\*\\*start of header")
  (setq tex-end-of-header "%\\*\\*end of header")
root's avatar
root committed
514
  (setq tex-trailer "\\bye\n")
515
  (run-hooks 'tex-mode-hook))
root's avatar
root committed
516

Roland McGrath's avatar
Roland McGrath committed
517
;;;###autoload
518
(define-derived-mode latex-mode text-mode "LaTeX"
root's avatar
root committed
519 520 521 522 523 524 525 526 527 528 529 530 531
  "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,
and '' when it appears to be the end; it inserts \" only after a \\.

Use \\[tex-region] to run LaTeX on the current region, plus the preamble
copied from the top of the file (containing \\documentstyle, etc.),
running LaTeX under a special subshell.  \\[tex-buffer] does the whole buffer.
\\[tex-file] saves the buffer and then processes the file.
\\[tex-print] prints the .dvi file made by any of these.
\\[tex-view] previews the .dvi file made by any of these.
\\[tex-bibtex-file] runs bibtex on the file of the current buffer.

532
Use \\[tex-validate-buffer] to check buffer for paragraphs containing
root's avatar
root committed
533 534 535 536 537 538 539 540 541 542 543 544 545
mismatched $'s or braces.

Special commands:
\\{tex-mode-map}

Mode variables:
latex-run-command
	Command string used by \\[tex-region] or \\[tex-buffer].
tex-directory
	Directory in which to create temporary files for LaTeX jobs
	run by \\[tex-region] or \\[tex-buffer].
tex-dvi-print-command
	Command string used by \\[tex-print] to print a .dvi file.
546 547 548
tex-alt-dvi-print-command
	Alternative command string used by \\[tex-print] (when given a prefix
	argument) to print a .dvi file.
root's avatar
root committed
549 550 551 552 553 554
tex-dvi-view-command
	Command string used by \\[tex-view] to preview a .dvi file.
tex-show-queue-command
	Command string used by \\[tex-show-print-queue] to show the print
	queue that \\[tex-print] put your job on.

555
Entering Latex mode runs the hook `text-mode-hook', then
Richard M. Stallman's avatar
Richard M. Stallman committed
556 557
`tex-mode-hook', and finally `latex-mode-hook'.  When the special
subshell is initiated, `tex-shell-hook' is run."
root's avatar
root committed
558 559
  (tex-common-initialization)
  (setq tex-command latex-run-command)
560 561
  (setq tex-start-of-header "\\\\documentstyle\\|\\\\documentclass")
  (setq tex-end-of-header "\\\\begin{document}")
root's avatar
root committed
562
  (setq tex-trailer "\\end{document}\n")
563 564 565
  ;; 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.
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
  (setq paragraph-start
	(concat "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$\\|"
		"\\\\[][]\\|"
		"\\\\" (regexp-opt (append
				    (mapcar 'car latex-section-alist)
				    '("begin" "label" "end"
				      "item" "bibitem" "newline" "noindent"
				      "newpage" "footnote" "marginpar"
				      "parbox" "caption")) t)
		"\\>\\|\\\\[a-z]*" (regexp-opt '("space" "skip" "page") t)
		"\\>"))
  (setq paragraph-separate
	(concat "[ \t]*$\\|[\f%]\\|[ \t]*\\$\\$[ \t]*$\\|"
		"\\\\[][]\\|"
		"\\\\" (regexp-opt (append
				    (mapcar 'car latex-section-alist)
				    '("begin" "label" "end" )) t)
		"\\>\\|\\\\\\(" (regexp-opt '("item" "bibitem" "newline"
					      "noindent" "newpage" "footnote"
					      "marginpar" "parbox" "caption"))
		"\\|[a-z]*\\(space\\|skip\\|page[a-z]*\\)"
		"\\)[ \t]*\\($\\|%\\)"))
  (set (make-local-variable 'imenu-create-index-function)
       'latex-imenu-create-index)
  (set (make-local-variable 'tex-face-alist) tex-latex-face-alist)
  (set (make-local-variable 'fill-nobreak-predicate)
       'latex-fill-nobreak-predicate)
  (set (make-local-variable 'outline-regexp) latex-outline-regexp)
  (set (make-local-variable 'outline-level) 'latex-outline-level)
  (run-hooks 'tex-mode-hook))
root's avatar
root committed
596

597
;;;###autoload
598
(define-derived-mode slitex-mode latex-mode "SliTeX"
root's avatar
root committed
599 600 601 602 603 604 605 606 607 608 609 610 611
  "Major mode for editing files of input for SliTeX.
Makes $ and } display the characters they match.
Makes \" insert `` when it seems to be the beginning of a quotation,
and '' when it appears to be the end; it inserts \" only after a \\.

Use \\[tex-region] to run SliTeX on the current region, plus the preamble
copied from the top of the file (containing \\documentstyle, etc.),
running SliTeX under a special subshell.  \\[tex-buffer] does the whole buffer.
\\[tex-file] saves the buffer and then processes the file.
\\[tex-print] prints the .dvi file made by any of these.
\\[tex-view] previews the .dvi file made by any of these.
\\[tex-bibtex-file] runs bibtex on the file of the current buffer.

612
Use \\[tex-validate-buffer] to check buffer for paragraphs containing
root's avatar
root committed
613 614 615 616 617 618 619 620 621 622 623 624 625
mismatched $'s or braces.

Special commands:
\\{tex-mode-map}

Mode variables:
slitex-run-command
	Command string used by \\[tex-region] or \\[tex-buffer].
tex-directory
	Directory in which to create temporary files for SliTeX jobs
	run by \\[tex-region] or \\[tex-buffer].
tex-dvi-print-command
	Command string used by \\[tex-print] to print a .dvi file.
626 627 628
tex-alt-dvi-print-command
	Alternative command string used by \\[tex-print] (when given a prefix
	argument) to print a .dvi file.
root's avatar
root committed
629 630 631 632 633 634
tex-dvi-view-command
	Command string used by \\[tex-view] to preview a .dvi file.
tex-show-queue-command
	Command string used by \\[tex-show-print-queue] to show the print
	queue that \\[tex-print] put your job on.

Richard M. Stallman's avatar
Richard M. Stallman committed
635 636 637 638
Entering SliTeX mode runs the hook `text-mode-hook', then the hook
`tex-mode-hook', then the hook `latex-mode-hook', and finally the hook
`slitex-mode-hook'.  When the special subshell is initiated, the hook
`tex-shell-hook' is run."
root's avatar
root committed
639
  (setq tex-command slitex-run-command)
640
  (setq tex-start-of-header "\\\\documentstyle{slides}\\|\\\\documentclass{slides}"))
root's avatar
root committed
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665

(defun tex-common-initialization ()
  (use-local-map tex-mode-map)
  (setq local-abbrev-table text-mode-abbrev-table)
  (if (null tex-mode-syntax-table)
      (let ((char 0))
	(setq tex-mode-syntax-table (make-syntax-table))
	(set-syntax-table tex-mode-syntax-table)
	(while (< char ? )
	  (modify-syntax-entry char ".")
	  (setq char (1+ char)))
	(modify-syntax-entry ?\C-@ "w")
	(modify-syntax-entry ?\t " ")
	(modify-syntax-entry ?\n ">")
	(modify-syntax-entry ?\f ">")
	(modify-syntax-entry ?$ "$$")
	(modify-syntax-entry ?% "<")
	(modify-syntax-entry ?\\ "/")
	(modify-syntax-entry ?\" ".")
	(modify-syntax-entry ?& ".")
	(modify-syntax-entry ?_ ".")
	(modify-syntax-entry ?@ "_")
	(modify-syntax-entry ?~ " ")
	(modify-syntax-entry ?' "w"))
    (set-syntax-table tex-mode-syntax-table))
666
  ;; Regexp isearch should accept newline and formfeed as whitespace.
667
  (set (make-local-variable 'search-whitespace-regexp) "[ \t\r\n\f]+")
668
  ;; A line containing just $$ is treated as a paragraph separator.
669 670
  (set (make-local-variable 'paragraph-start)
       "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$")
671 672
  ;; A line starting with $$ starts a paragraph,
  ;; but does not separate paragraphs if it has more stuff on it.
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
  (set (make-local-variable 'paragraph-separate)
	"[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$[ \t]*$")
  (set (make-local-variable 'comment-start) "%")
  (set (make-local-variable 'comment-add) 1)
  (set (make-local-variable 'comment-start-skip)
       "\\(\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)")
  (set (make-local-variable 'comment-indent-function) 'tex-comment-indent)
  (set (make-local-variable 'parse-sexp-ignore-comments) t)
  (set (make-local-variable 'compare-windows-whitespace)
       'tex-categorize-whitespace)
  (set (make-local-variable 'facemenu-add-face-function)
       (lambda (face end)
	 (let ((face-text (cdr (assq face tex-face-alist))))
	   (if face-text
	       face-text
	     (error "Face %s not configured for %s mode" face mode-name)))))
  (set (make-local-variable 'facemenu-end-add-face) "}")
  (set (make-local-variable 'facemenu-remove-face-function) t)
  (set (make-local-variable 'font-lock-defaults)
       '((tex-font-lock-keywords
	  tex-font-lock-keywords-1 tex-font-lock-keywords-2)
	 nil nil ((?$ . "\"")) nil
	 ;; Who ever uses that anyway ???
	 (font-lock-mark-block-function . mark-paragraph)))
root's avatar
root committed
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
  (make-local-variable 'tex-command)
  (make-local-variable 'tex-start-of-header)
  (make-local-variable 'tex-end-of-header)
  (make-local-variable 'tex-trailer))

(defun tex-comment-indent ()
  (if (looking-at "%%%")
      (current-column)
    (skip-chars-backward " \t")
    (max (if (bolp) 0 (1+ (current-column)))
	 comment-column)))

(defun tex-categorize-whitespace (backward-limit)
  ;; compare-windows-whitespace is set to this.
  ;; This is basically a finite-state machine.
  ;; Returns a symbol telling how TeX would treat
  ;; the whitespace we are looking at: null, space, or par.
  (let ((category 'null)
	(not-finished t))
    (skip-chars-backward " \t\n\f" backward-limit)
    (while not-finished
      (cond ((looking-at "[ \t]+")
	     (goto-char (match-end 0))
720
	     (if (eq category 'null)
root's avatar
root committed
721 722
		 (setq category 'space)))
	    ((looking-at "\n")
723
	     (cond ((eq category 'newline)
root's avatar
root committed
724 725 726 727 728 729 730 731 732 733 734
		    (setq category 'par)
		    (setq not-finished nil))
		   (t
		    (setq category 'newline) ;a strictly internal state
		    (goto-char (match-end 0)))))
	    ((looking-at "\f+")
	     (setq category 'par)
	     (setq not-finished nil))
	    (t
	     (setq not-finished nil))))
    (skip-chars-forward " \t\n\f")
735
    (if (eq category 'newline)
root's avatar
root committed
736 737 738 739 740
	'space				;TeX doesn't distinguish
      category)))

(defun tex-insert-quote (arg)
  "Insert the appropriate quote marks for TeX.
741 742
Inserts the value of `tex-open-quote' (normally ``) or `tex-close-quote'
\(normally '') depending on the context.  With prefix argument, always
root's avatar
root committed
743
inserts \" characters."
744
  (interactive "*P")
root's avatar
root committed
745 746 747 748 749 750 751 752 753 754 755 756 757
  (if arg
      (self-insert-command (prefix-numeric-value arg))
    (insert
     (cond ((or (bobp)
		(save-excursion
		  (forward-char -1)
		  (looking-at "\\s(\\|\\s \\|\\s>")))
	    tex-open-quote)
	   ((= (preceding-char) ?\\)
	    ?\")
	   (t
	    tex-close-quote)))))

758 759
(defun tex-validate-buffer ()
  "Check current buffer for paragraphs containing mismatched braces or $s.
760
Their positions are recorded in the buffer `*Occur*'.
761 762 763
To find a particular invalidity from `*Occur*', switch to that buffer
and type C-c C-c or click with mouse-2
on the line for the invalidity you want to see."
root's avatar
root committed
764
  (interactive)
765 766
  (let ((buffer (current-buffer))
	(prevpos (point-min))
767 768
	(linenum nil)
	(num-matches 0))
769 770 771 772 773 774
    (with-output-to-temp-buffer "*Occur*"
      (princ "Mismatches:\n")
      (save-excursion
	(set-buffer standard-output)
	(occur-mode)
	(setq occur-buffer buffer)
775
	(setq occur-nlines 0))
776 777
      (save-excursion
	(goto-char (point-max))
root's avatar
root committed
778
	(while (and (not (input-pending-p)) (not (bobp)))
779 780
	  (let ((end (point))
		prev-end)
781
	    ;; Scan the previous paragraph for invalidities.
782 783 784 785 786
	    (if (search-backward "\n\n" nil t)
		(progn
		  (setq prev-end (point))
		  (forward-char 2))
	      (goto-char (setq prev-end (point-min))))
root's avatar
root committed
787
	    (or (tex-validate-region (point) end)
788 789
		(let* ((oend end)
		       (end (save-excursion (forward-line 1) (point)))
790 791 792 793 794 795 796 797 798
		       start tem)
		  (beginning-of-line)
		  (setq start (point))
		  ;; Keep track of line number as we scan,
		  ;; in a cumulative fashion.
		  (if linenum
		      (setq linenum (- linenum (count-lines prevpos (point))))
		    (setq linenum (1+ (count-lines 1 start))))
		  (setq prevpos (point))
799
		  ;; Mention this mismatch in *Occur*.
800
		  ;; Since we scan from end of buffer to beginning,
801
		  ;; add each mismatch at the beginning of *Occur*.
802 803 804 805 806 807
		  (save-excursion
		    (setq tem (point-marker))
		    (set-buffer standard-output)
		    (goto-char (point-min))
		    ;; Skip "Mismatches:" header line.
		    (forward-line 1)
808
		    (setq num-matches (1+ num-matches))
809
		    (insert-buffer-substring buffer start end)
810 811 812 813 814 815 816 817 818 819
		    (let (text-beg (text-end (point-marker)))
		      (forward-char (- start end))
		      (setq text-beg (point-marker))
		      (insert (format "%3d: " linenum))
		      (put-text-property (marker-position text-beg)
					 (- (marker-position text-end) 1)
					 'mouse-face 'highlight)
		      (put-text-property (marker-position text-beg)
					 (- (marker-position text-end) 1)
					 'occur tem)))))
820
	    (goto-char prev-end))))
821 822
      (save-excursion
	(set-buffer standard-output)
823
	(if (eq num-matches 0)
824 825
	    (insert "None!\n"))
	(if (interactive-p)
826
	    (message "%d mismatches found" num-matches))))))
root's avatar
root committed
827 828 829 830 831 832 833 834 835 836 837

(defun tex-validate-region (start end)
  "Check for mismatched braces or $'s in region.
Returns t if no mismatches.  Returns nil and moves point to suspect
area if a mismatch is found."
  (interactive "r")
  (let ((failure-point nil) (max-possible-sexps (- end start)))
    (save-excursion
      (condition-case ()
	  (save-restriction
	    (narrow-to-region start end)
838
	    ;; First check that the open and close parens balance in numbers.
root's avatar
root committed
839
	    (goto-char start)
840
	    (while (<= 0 (setq max-possible-sexps (1- max-possible-sexps)))
841 842 843 844 845 846 847 848 849 850 851
	      (forward-sexp 1))
	    ;; Now check that like matches like.
	    (goto-char start)
	    (while (progn (skip-syntax-forward "^(")
			  (not (eobp)))
	      (let ((match (matching-paren (following-char))))
		(save-excursion
		  (forward-sexp 1)
		  (or (= (preceding-char) match)
		      (error "Mismatched parentheses"))))
	      (forward-char 1)))
root's avatar
root committed
852
	(error
853 854
	 (skip-syntax-forward " .>")
	 (setq failure-point (point)))))
root's avatar
root committed
855 856 857 858 859 860 861 862
    (if failure-point
	(progn
	  (goto-char failure-point)
	  nil)
      t)))

(defun tex-terminate-paragraph (inhibit-validation)
  "Insert two newlines, breaking a paragraph for TeX.
Richard M. Stallman's avatar
Richard M. Stallman committed
863
Check for mismatched braces or $s in paragraph being terminated.
root's avatar
root committed
864
A prefix arg inhibits the checking."
865
  (interactive "*P")
root's avatar
root committed
866 867 868
  (or inhibit-validation
      (save-excursion
	(tex-validate-region
869 870 871 872
	 (save-excursion
	   (search-backward "\n\n" nil 'move)
	   (point))
	 (point)))
root's avatar
root committed
873 874 875 876 877
      (message "Paragraph being closed appears to contain a mismatch"))
  (insert "\n\n"))

(defun tex-insert-braces ()
  "Make a pair of braces and be poised to type inside of them."
878
  (interactive "*")
root's avatar
root committed
879 880 881 882
  (insert ?\{)
  (save-excursion
    (insert ?})))

883 884 885 886 887 888
;; This function is used as the value of fill-nobreak-predicate
;; in LaTeX mode.  Its job is to prevent line-breaking inside
;; of a \verb construct.
(defun latex-fill-nobreak-predicate ()
  (let ((opoint (point))
	inside)
889
    (save-excursion
890 891 892 893 894 895 896 897
      (save-restriction
	(beginning-of-line)
	(narrow-to-region (point) opoint)
	(while (re-search-forward "\\\\verb\\(.\\)" nil t)
	  (unless (re-search-forward (regexp-quote (match-string 1)) nil t)
	    (setq inside t)))))
    inside))

root's avatar
root committed
898
;;; Like tex-insert-braces, but for LaTeX.
899 900
(define-skeleton tex-latex-block
  "Create a matching pair of lines \\begin[OPT]{NAME} and \\end{NAME} at point.
root's avatar
root committed
901
Puts point on a blank line between them."
902 903 904 905 906 907 908 909 910 911 912
  (completing-read "LaTeX block name: "
		   (mapcar 'list
			   (append standard-latex-block-names
				   latex-block-names)))
  "\\begin["
  (skeleton-read "[options]: ") & ?\] | -1
  ?\{
  str
  ?\} \n
  _ \n
  "\\end{" str ?\})
root's avatar
root committed
913 914

(defun tex-last-unended-begin ()
Richard M. Stallman's avatar
Richard M. Stallman committed
915
  "Leave point at the beginning of the last `\\begin{...}' that is unended."
root's avatar
root committed
916 917 918 919
  (while (and (re-search-backward "\\(\\\\begin\\s *{\\)\\|\\(\\\\end\\s *{\\)")
              (looking-at "\\\\end{"))
    (tex-last-unended-begin)))

920 921 922 923 924 925 926 927 928 929 930 931 932
(defun tex-goto-last-unclosed-latex-block ()
  "Move point to the last unclosed \\begin{...}.
Mark is left at original location."
  (interactive)
  (let ((spot))
    (save-excursion
      (condition-case nil
          (tex-last-unended-begin)
        (error (error "Couldn't find unended \\begin")))
      (setq spot (point)))
    (push-mark)
    (goto-char spot)))

root's avatar
root committed
933 934 935 936 937 938
(defun tex-close-latex-block ()
  "Creates an \\end{...} to match the last unclosed \\begin{...}."
  (interactive "*")
  (let ((new-line-needed (bolp))
	text indentation)
    (save-excursion
939
      (condition-case nil
root's avatar
root committed
940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955
          (tex-last-unended-begin)
        (error (error "Couldn't find unended \\begin")))
      (setq indentation (current-column))
      (re-search-forward "\\\\begin\\(\\s *{[^}\n]*}\\)")
      (setq text (buffer-substring (match-beginning 1) (match-end 1))))
    (indent-to indentation)
    (insert "\\end" text)
    (if new-line-needed (insert ?\n))))

;;; Invoking TeX in an inferior shell.

;;; Why use a shell instead of running TeX directly?  Because if TeX
;;; gets stuck, the user can switch to the shell window and type at it.

;;; The utility functions:

956
;;;###autoload
root's avatar
root committed
957
(defun tex-start-shell ()
958 959 960 961 962
  (with-current-buffer
      (make-comint
       "tex-shell"
       (or tex-shell-file-name (getenv "ESHELL") (getenv "SHELL") "/bin/sh")
       nil)
963 964 965
    (let ((proc (get-process "tex-shell")))
      (set-process-sentinel proc 'tex-shell-sentinel)
      (process-kill-without-query proc)
966
      (setq comint-prompt-regexp shell-prompt-pattern)
967
      (use-local-map tex-shell-map)
968
      (compilation-shell-minor-mode t)
969 970 971 972 973
      (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t)
      (make-local-variable 'list-buffers-directory)
      (make-local-variable 'shell-dirstack)
      (make-local-variable 'shell-last-dir)
      (make-local-variable 'shell-dirtrackp)
974
      (run-hooks 'tex-shell-hook)
975
      (while (zerop (buffer-size))
976 977
	(sleep-for 1)))))

978 979 980
(defun tex-feed-input ()
  "Send input to the tex shell process.
In the tex buffer this can be used to continue an interactive tex run.
981
In the tex shell buffer this command behaves like `comint-send-input'."
982 983 984 985 986
  (interactive)
  (set-buffer (process-buffer (get-process "tex-shell")))
  (comint-send-input)
  (tex-recenter-output-buffer nil))

987 988 989 990
(defun tex-display-shell ()
  "Make the TeX shell buffer visible in a window."
  (display-buffer (process-buffer (get-process "tex-shell")))
  (tex-recenter-output-buffer nil))
991 992 993 994 995 996 997 998 999 1000

(defun tex-shell-sentinel (proc msg)
  (cond ((null (buffer-name (process-buffer proc)))
	 ;; buffer killed
	 (set-process-buffer proc nil)
         (tex-delete-last-temp-files))
	((memq (process-status proc) '(signal exit))
         (tex-delete-last-temp-files))))

(defun tex-set-buffer-directory (buffer directory)
root's avatar
root committed
1001 1002 1003 1004 1005 1006 1007 1008
  "Set BUFFER's default directory to be DIRECTORY."
  (setq directory (file-name-as-directory (expand-file-name directory)))
  (if (not (file-directory-p directory))
      (error "%s is not a directory" directory)
    (save-excursion
      (set-buffer buffer)
      (setq default-directory directory))))

1009 1010 1011
(defvar tex-send-command-modified-tick 0)
(make-variable-buffer-local 'tex-send-command-modified-tick)

1012
(defun tex-send-command (command &optional file background)
1013
  "Send COMMAND to TeX shell process, substituting optional FILE for *.
1014 1015 1016
Do this in background if optional BACKGROUND is t.  If COMMAND has no *,
FILE will be appended, preceded by a blank, to COMMAND.  If FILE is nil, no
substitution will be made in COMMAND.  COMMAND can be any expression that
1017 1018 1019
evaluates to a command string.

Return the process in which TeX is running."
1020 1021
  (save-excursion
    (let* ((cmd (eval command))
1022
	   (proc (or (get-process "tex-shell") (error "No TeX subprocess")))
1023
	   (buf (process-buffer proc))
1024
           (star (string-match "\\*" cmd))
1025 1026 1027 1028 1029 1030 1031 1032
	   (string
	    (concat
	     (if file
		 (if star (concat (substring cmd 0 star)
				  file (substring cmd (1+ star)))
		   (concat cmd " " file))
	       cmd)
	     (if background "&" ""))))
1033 1034
      ;; Switch to buffer before checking for subproc output in it.
      (set-buffer buf)
1035 1036
      ;; If text is unchanged since previous tex-send-command,
      ;; we haven't got any output.  So wait for output now.
1037
      (if (= (buffer-modified-tick buf) tex-send-command-modified-tick)
1038
	  (accept-process-output proc))
1039 1040
      (goto-char (process-mark proc))
      (insert string)
1041
      (comint-send-input)
1042 1043
      (setq tex-send-command-modified-tick (buffer-modified-tick buf))
      proc)))
1044

1045 1046 1047
(defun tex-delete-last-temp-files (&optional not-all)
  "Delete any junk files from last temp file.
If NOT-ALL is non-nil, save the `.dvi' file."
1048 1049
  (if tex-last-temp-file
      (let* ((dir (file-name-directory tex-last-temp-file))
1050 1051
	     (list (and (file-directory-p dir)
			(file-name-all-completions
1052 1053 1054
			 (file-name-sans-extension
			  (file-name-nondirectory tex-last-temp-file))
			 dir))))
1055
	(while list
1056 1057 1058 1059 1060 1061
	  (if not-all
	      (and
	       ;; If arg is non-nil, don't delete the .dvi file.
	       (not (string-match "\\.dvi$" (car list)))
	       (delete-file (concat dir (car list))))
	    (delete-file (concat dir (car list))))
1062 1063
          (setq list (cdr list))))))

1064
(add-hook 'kill-emacs-hook 'tex-delete-last-temp-files)
root's avatar
root committed
1065

1066 1067 1068
(defvar tex-start-tex-marker nil
  "Marker pointing after last TeX-running command in the TeX shell buffer.")

1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
(defun tex-main-file ()
  (let ((file (or tex-main-file
		  ;; Compatibility with AUCTeX
		  (and (boundp 'TeX-master) (stringp TeX-master) TeX-master)
		  (if (buffer-file-name)
		      (file-relative-name (buffer-file-name))
		    (error "Buffer is not associated with any file")))))
    (if (string-match "\\.tex\\'" file)
	(substring file 0 (match-beginning 0))
      file)))

(defun tex-start-tex (command file &optional dir)
1081
  "Start a TeX run, using COMMAND on FILE."
Karl Heuer's avatar
Karl Heuer committed
1082
  (let* ((star (string-match "\\*" command))
Richard M. Stallman's avatar