|
|
1.1 ! root 1: ;; TeX mode commands. ! 2: ;; Copyright (C) 1985, 1986 Free Software Foundation, Inc. ! 3: ;; Rewritten following contributions by William F. Schelter ! 4: ;; and Dick King (king@kestrel). ! 5: ;; Modified August 1986 by Stephen Gildea <mit-erl!gildea> and ! 6: ;; Michael Prange <mit-erl!prange> to add LaTeX support and enhance ! 7: ;; TeX-region. ! 8: ;; Added TeX-directory and reorganized somewhat gildea 21 Nov 86 ! 9: ! 10: ;; This file is part of GNU Emacs. ! 11: ! 12: ;; GNU Emacs is free software; you can redistribute it and/or modify ! 13: ;; it under the terms of the GNU General Public License as published by ! 14: ;; the Free Software Foundation; either version 1, or (at your option) ! 15: ;; any later version. ! 16: ! 17: ;; GNU Emacs is distributed in the hope that it will be useful, ! 18: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ! 19: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 20: ;; GNU General Public License for more details. ! 21: ! 22: ;; You should have received a copy of the GNU General Public License ! 23: ;; along with GNU Emacs; see the file COPYING. If not, write to ! 24: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ! 25: ! 26: ;; Still to do: ! 27: ;; Make TAB indent correctly for TeX code. Then we can make linefeed ! 28: ;; do something more useful. ! 29: ;; ! 30: ;; Have spell understand TeX instead of assuming the entire world ! 31: ;; uses nroff. ! 32: ;; ! 33: ;; The code for finding matching $ needs to be fixed. ! 34: ! 35: (provide 'tex-mode) ! 36: ! 37: (defvar TeX-directory "/tmp/" ! 38: "*Directory in which to run TeX subjob. Temporary files are ! 39: created in this directory.") ! 40: (defvar TeX-dvi-print-command "lpr -d" ! 41: "*Command string used by \\[TeX-print] to print a .dvi file.") ! 42: (defvar TeX-show-queue-command "lpq" ! 43: "*Command string used by \\[TeX-show-print-queue] to show the print queue ! 44: that \\[TeX-print] put your job on.") ! 45: (defvar TeX-default-mode 'plain-TeX-mode ! 46: "*Mode to enter for a new file when it can't be determined whether ! 47: the file is plain TeX or LaTeX or what.") ! 48: ! 49: (defvar TeX-command nil ! 50: "The command to run TeX on a file. The name of the file will be appended ! 51: to this string, separated by a space.") ! 52: (defvar TeX-trailer nil ! 53: "String appended after the end of a region sent to TeX by \\[TeX-region].") ! 54: (defvar TeX-start-of-header nil ! 55: "String used by \\[TeX-region] to delimit the start of the file's header.") ! 56: (defvar TeX-end-of-header nil ! 57: "String used by \\[TeX-region] to delimit the end of the file's header.") ! 58: (defvar TeX-shell-cd-command "cd" ! 59: "Command to give to shell running TeX to change directory. The value of ! 60: TeX-directory will be appended to this, separated by a space.") ! 61: (defvar TeX-zap-file nil ! 62: "Temporary file name used for text being sent as input to TeX. ! 63: Should be a simple file name with no extension or directory specification.") ! 64: ! 65: (defvar TeX-mode-syntax-table nil ! 66: "Syntax table used while in TeX mode.") ! 67: ! 68: (defun TeX-define-common-keys (keymap) ! 69: "Define the keys that we want defined both in TeX-mode ! 70: and in the TeX-shell." ! 71: (define-key keymap "\C-c\C-k" 'TeX-kill-job) ! 72: (define-key keymap "\C-c\C-l" 'TeX-recenter-output-buffer) ! 73: (define-key keymap "\C-c\C-q" 'TeX-show-print-queue) ! 74: (define-key keymap "\C-c\C-p" 'TeX-print) ! 75: ) ! 76: ! 77: (defvar TeX-mode-map nil "Keymap for TeX mode") ! 78: ! 79: (if TeX-mode-map ! 80: nil ! 81: (setq TeX-mode-map (make-sparse-keymap)) ! 82: (TeX-define-common-keys TeX-mode-map) ! 83: (define-key TeX-mode-map "\"" 'TeX-insert-quote) ! 84: (define-key TeX-mode-map "\n" 'TeX-terminate-paragraph) ! 85: (define-key TeX-mode-map "\e}" 'up-list) ! 86: (define-key TeX-mode-map "\e{" 'TeX-insert-braces) ! 87: (define-key TeX-mode-map "\C-c\C-r" 'TeX-region) ! 88: (define-key TeX-mode-map "\C-c\C-b" 'TeX-buffer) ! 89: (define-key TeX-mode-map "\C-c\C-f" 'TeX-close-LaTeX-block) ! 90: ) ! 91: ! 92: (defvar TeX-shell-map nil ! 93: "Keymap for the TeX shell. A shell-mode-map with a few additions") ! 94: ! 95: ;(fset 'TeX-mode 'tex-mode) ;in loaddefs. ! 96: ! 97: ;;; This would be a lot simpler if we just used a regexp search, ! 98: ;;; but then it would be too slow. ! 99: (defun tex-mode () ! 100: "Major mode for editing files of input for TeX or LaTeX. ! 101: Trys to intuit whether this file is for plain TeX or LaTeX and ! 102: calls plain-tex-mode or latex-mode. If it cannot be determined ! 103: \(e.g., there are no commands in the file), the value of ! 104: TeX-default-mode is used." ! 105: (interactive) ! 106: (let (mode slash comment) ! 107: (save-excursion ! 108: (goto-char (point-min)) ! 109: (while (and (setq slash (search-forward "\\" nil t)) ! 110: (setq comment (let ((search-end (point))) ! 111: (save-excursion ! 112: (beginning-of-line) ! 113: (search-forward "%" search-end t)))))) ! 114: (if (and slash (not comment)) ! 115: (setq mode (if (looking-at "documentstyle") ! 116: 'latex-mode ! 117: 'plain-tex-mode)))) ! 118: (if mode (funcall mode) ! 119: (funcall TeX-default-mode)))) ! 120: ! 121: (fset 'plain-TeX-mode 'plain-tex-mode) ! 122: (fset 'LaTeX-mode 'latex-mode) ! 123: ! 124: (defun plain-tex-mode () ! 125: "Major mode for editing files of input for plain TeX. ! 126: Makes $ and } display the characters they match. ! 127: Makes \" insert `` when it seems to be the beginning of a quotation, ! 128: and '' when it appears to be the end; it inserts \" only after a \\. ! 129: ! 130: Use \\[TeX-region] to run TeX on the current region, plus a \"header\" ! 131: copied from the top of the file (containing macro definitions, etc.), ! 132: running TeX under a special subshell. \\[TeX-buffer] does the whole buffer. ! 133: \\[TeX-print] prints the .dvi file made by either of these. ! 134: ! 135: Use \\[validate-TeX-buffer] to check buffer for paragraphs containing ! 136: mismatched $'s or braces. ! 137: ! 138: Special commands: ! 139: \\{TeX-mode-map} ! 140: ! 141: Mode variables: ! 142: TeX-directory ! 143: Directory in which to create temporary files for TeX jobs ! 144: run by \\[TeX-region] or \\[TeX-buffer]. ! 145: TeX-dvi-print-command ! 146: Command string used by \\[TeX-print] to print a .dvi file. ! 147: TeX-show-queue-command ! 148: Command string used by \\[TeX-show-print-queue] to show the print ! 149: queue that \\[TeX-print] put your job on. ! 150: ! 151: Entering plain-TeX mode calls the value of text-mode-hook, ! 152: then the value of TeX-mode-hook, and then the value ! 153: of plain-TeX-mode-hook." ! 154: (interactive) ! 155: (TeX-common-initialization) ! 156: (setq mode-name "TeX") ! 157: (setq major-mode 'plain-TeX-mode) ! 158: (setq TeX-command "tex") ! 159: (setq TeX-start-of-header "%**start of header") ! 160: (setq TeX-end-of-header "%**end of header") ! 161: (setq TeX-trailer "\\bye\n") ! 162: (run-hooks 'text-mode-hook 'TeX-mode-hook 'plain-TeX-mode-hook)) ! 163: ! 164: (defun latex-mode () ! 165: "Major mode for editing files of input for LaTeX. ! 166: Makes $ and } display the characters they match. ! 167: Makes \" insert `` when it seems to be the beginning of a quotation, ! 168: and '' when it appears to be the end; it inserts \" only after a \\. ! 169: ! 170: Use \\[TeX-region] to run LaTeX on the current region, plus the preamble ! 171: copied from the top of the file (containing \\documentstyle, etc.), ! 172: running LaTeX under a special subshell. \\[TeX-buffer] does the whole buffer. ! 173: \\[TeX-print] prints the .dvi file made by either of these. ! 174: ! 175: Use \\[validate-TeX-buffer] to check buffer for paragraphs containing ! 176: mismatched $'s or braces. ! 177: ! 178: Special commands: ! 179: \\{TeX-mode-map} ! 180: ! 181: Mode variables: ! 182: TeX-directory ! 183: Directory in which to create temporary files for TeX jobs ! 184: run by \\[TeX-region] or \\[TeX-buffer]. ! 185: TeX-dvi-print-command ! 186: Command string used by \\[TeX-print] to print a .dvi file. ! 187: TeX-show-queue-command ! 188: Command string used by \\[TeX-show-print-queue] to show the print ! 189: queue that \\[TeX-print] put your job on. ! 190: ! 191: Entering LaTeX mode calls the value of text-mode-hook, ! 192: then the value of TeX-mode-hook, and then the value ! 193: of LaTeX-mode-hook." ! 194: (interactive) ! 195: (TeX-common-initialization) ! 196: (setq mode-name "LaTeX") ! 197: (setq major-mode 'LaTeX-mode) ! 198: (setq TeX-command "latex") ! 199: (setq TeX-start-of-header "\\documentstyle") ! 200: (setq TeX-end-of-header "\\begin{document}") ! 201: (setq TeX-trailer "\\end{document}\n") ! 202: (run-hooks 'text-mode-hook 'TeX-mode-hook 'LaTeX-mode-hook)) ! 203: ! 204: (defun TeX-common-initialization () ! 205: (kill-all-local-variables) ! 206: (use-local-map TeX-mode-map) ! 207: (setq local-abbrev-table text-mode-abbrev-table) ! 208: (if (null TeX-mode-syntax-table) ! 209: (progn ! 210: (setq TeX-mode-syntax-table (make-syntax-table)) ! 211: (set-syntax-table TeX-mode-syntax-table) ! 212: (modify-syntax-entry ?\\ ".") ! 213: (modify-syntax-entry ?\f ">") ! 214: (modify-syntax-entry ?\n ">") ! 215: (modify-syntax-entry ?$ "$$") ! 216: (modify-syntax-entry ?% "<") ! 217: (modify-syntax-entry ?\" ".") ! 218: (modify-syntax-entry ?& ".") ! 219: (modify-syntax-entry ?_ ".") ! 220: (modify-syntax-entry ?@ "_") ! 221: (modify-syntax-entry ?~ " ") ! 222: (modify-syntax-entry ?' "w")) ! 223: (set-syntax-table TeX-mode-syntax-table)) ! 224: (make-local-variable 'paragraph-start) ! 225: (setq paragraph-start "^[ \t]*$\\|^[\f\\\\%]") ! 226: (make-local-variable 'paragraph-separate) ! 227: (setq paragraph-separate paragraph-start) ! 228: (make-local-variable 'comment-start) ! 229: (setq comment-start "%") ! 230: (make-local-variable 'comment-start-skip) ! 231: (setq comment-start-skip "\\(\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)") ! 232: (make-local-variable 'comment-indent-hook) ! 233: (setq comment-indent-hook 'TeX-comment-indent) ! 234: (make-local-variable 'TeX-command) ! 235: (make-local-variable 'TeX-start-of-header) ! 236: (make-local-variable 'TeX-end-of-header) ! 237: (make-local-variable 'TeX-trailer)) ! 238: ! 239: (defun TeX-comment-indent () ! 240: (if (looking-at "%%%") ! 241: (current-column) ! 242: (skip-chars-backward " \t") ! 243: (max (if (bolp) 0 (1+ (current-column))) ! 244: comment-column))) ! 245: ! 246: (defun TeX-insert-quote (arg) ! 247: "Insert ``, '' or \" according to preceding character. ! 248: With prefix argument, always insert \" characters." ! 249: (interactive "P") ! 250: (if arg ! 251: (let ((count (prefix-numeric-value arg))) ! 252: (if (listp arg) ! 253: (self-insert-command 1) ;C-u always inserts just one ! 254: (self-insert-command count))) ! 255: (insert ! 256: (cond ! 257: ((or (bobp) ! 258: (save-excursion ! 259: (forward-char -1) ! 260: (looking-at "[ \t\n]\\|\\s("))) ! 261: "``") ! 262: ((= (preceding-char) ?\\) ! 263: ?\") ! 264: (t "''"))))) ! 265: ! 266: (defun validate-TeX-buffer () ! 267: "Check current buffer for paragraphs containing mismatched $'s. ! 268: As each such paragraph is found, a mark is pushed at its beginning, ! 269: and the location is displayed for a few seconds." ! 270: (interactive) ! 271: (let ((opoint (point))) ! 272: (goto-char (point-max)) ! 273: ;; Does not use save-excursion ! 274: ;; because we do not want to save the mark. ! 275: (unwind-protect ! 276: (while (and (not (input-pending-p)) (not (bobp))) ! 277: (let ((end (point))) ! 278: (search-backward "\n\n" nil 'move) ! 279: (or (TeX-validate-paragraph (point) end) ! 280: (progn ! 281: (push-mark (point)) ! 282: (message "Mismatch found in pararaph starting here") ! 283: (sit-for 4))))) ! 284: (goto-char opoint)))) ! 285: ! 286: (defun TeX-validate-paragraph (start end) ! 287: (condition-case () ! 288: (save-excursion ! 289: (save-restriction ! 290: (narrow-to-region start end) ! 291: (goto-char start) ! 292: (forward-sexp (- end start)) ! 293: t)) ! 294: (error nil))) ! 295: ! 296: (defun TeX-terminate-paragraph (inhibit-validation) ! 297: "Insert two newlines, breaking a paragraph for TeX. ! 298: Check for mismatched braces/$'s in paragraph being terminated. ! 299: A prefix arg inhibits the checking." ! 300: (interactive "P") ! 301: (or inhibit-validation ! 302: (TeX-validate-paragraph ! 303: (save-excursion ! 304: (search-backward "\n\n" nil 'move) ! 305: (point)) ! 306: (point)) ! 307: (message "Paragraph being closed appears to contain a mismatch")) ! 308: (insert "\n\n")) ! 309: ! 310: (defun TeX-insert-braces () ! 311: "Make a pair of braces and be poised to type inside of them." ! 312: (interactive) ! 313: (insert ?\{) ! 314: (save-excursion ! 315: (insert ?}))) ! 316: ! 317: ;;; Like TeX-insert-braces, but for LaTeX. ! 318: (defun TeX-close-LaTeX-block () ! 319: "Creates an \\end{...} to match \\begin{...} on the current line and ! 320: puts point on the blank line between them." ! 321: (interactive "*") ! 322: (let ((fail-point (point))) ! 323: (end-of-line) ! 324: (if (re-search-backward "\\\\begin{\\([^}\n]*\\)}" ! 325: (save-excursion (beginning-of-line) (point)) t) ! 326: (let ((text (buffer-substring (match-beginning 1) (match-end 1))) ! 327: (indentation (current-column))) ! 328: (end-of-line) ! 329: (delete-horizontal-space) ! 330: (insert "\n\n") ! 331: (indent-to indentation) ! 332: (insert "\\end{" text "}") ! 333: (forward-line -1)) ! 334: (goto-char fail-point) ! 335: (ding)))) ! 336: ! 337: ;;; Invoking TeX in an inferior shell. ! 338: ! 339: ;;; Why use a shell instead of running TeX directly? Because if TeX ! 340: ;;; gets stuck, the user can switch to the shell window and type at it. ! 341: ! 342: ;;; The utility functions: ! 343: ! 344: (defun TeX-start-shell () ! 345: (require 'shell) ! 346: (save-excursion ! 347: (set-buffer (make-shell "TeX-shell" nil nil "-v")) ! 348: (setq TeX-shell-map (copy-keymap shell-mode-map)) ! 349: (TeX-define-common-keys TeX-shell-map) ! 350: (use-local-map TeX-shell-map) ! 351: (if (zerop (buffer-size)) ! 352: (sleep-for 1)))) ! 353: ! 354: (defun set-buffer-directory (buffer directory) ! 355: "Set BUFFER's default directory to be DIRECTORY." ! 356: (setq directory (file-name-as-directory (expand-file-name directory))) ! 357: (if (not (file-directory-p directory)) ! 358: (error "%s is not a directory" directory) ! 359: (save-excursion ! 360: (set-buffer buffer) ! 361: (setq default-directory directory)))) ! 362: ! 363: ;;; The commands: ! 364: ! 365: ;;; It's a kludge that we have to create a special buffer just ! 366: ;;; to write out the TeX-trailer. It would nice if there were a ! 367: ;;; function like write-region that would write literal strings. ! 368: ! 369: (defun TeX-region (beg end) ! 370: "Run TeX on the current region. A temporary file (TeX-zap-file) is ! 371: written in directory TeX-directory, and TeX is run in that directory. ! 372: If the buffer has a header, it is written to the temporary file before ! 373: the region itself. The buffer's header is all lines between the ! 374: strings defined by TeX-start-of-header and TeX-end-of-header ! 375: inclusive. The header must start in the first 100 lines. The value ! 376: of TeX-trailer is appended to the temporary file after the region." ! 377: (interactive "r") ! 378: (if (get-buffer "*TeX-shell*") ! 379: (TeX-kill-job) ! 380: (TeX-start-shell)) ! 381: (or TeX-zap-file (setq TeX-zap-file (make-temp-name "#tz"))) ! 382: (let ((tex-out-file (concat TeX-zap-file ".tex")) ! 383: (temp-buffer (get-buffer-create " TeX-Output-Buffer")) ! 384: (zap-directory ! 385: (file-name-as-directory (expand-file-name TeX-directory)))) ! 386: (save-excursion ! 387: (save-restriction ! 388: (widen) ! 389: (goto-char (point-min)) ! 390: (forward-line 100) ! 391: (let ((search-end (point)) ! 392: (hbeg (point-min)) (hend (point-min)) ! 393: (default-directory zap-directory)) ! 394: (goto-char (point-min)) ! 395: ;; Initialize the temp file with either the header or nothing ! 396: (if (search-forward TeX-start-of-header search-end t) ! 397: (progn ! 398: (beginning-of-line) ! 399: (setq hbeg (point)) ;mark beginning of header ! 400: (if (search-forward TeX-end-of-header nil t) ! 401: (progn (forward-line 1) ! 402: (setq hend (point))) ;mark end of header ! 403: (setq hbeg (point-min))))) ;no header ! 404: (write-region (min hbeg beg) hend tex-out-file nil nil) ! 405: (write-region (max beg hend) end tex-out-file t nil)) ! 406: (let ((local-tex-trailer TeX-trailer)) ! 407: (set-buffer temp-buffer) ! 408: (erase-buffer) ! 409: ;; make sure trailer isn't hidden by a comment ! 410: (insert-string "\n") ! 411: (if local-tex-trailer (insert-string local-tex-trailer)) ! 412: (set-buffer-directory temp-buffer zap-directory) ! 413: (write-region (point-min) (point-max) tex-out-file t nil)))) ! 414: (set-buffer-directory "*TeX-shell*" zap-directory) ! 415: (send-string "TeX-shell" (concat TeX-shell-cd-command " " ! 416: zap-directory "\n")) ! 417: (send-string "TeX-shell" (concat TeX-command " \"" ! 418: tex-out-file "\"\n"))) ! 419: (TeX-recenter-output-buffer 0)) ! 420: ! 421: (defun TeX-buffer () ! 422: "Run TeX on current buffer. See \\[TeX-region] for more information." ! 423: (interactive) ! 424: (TeX-region (point-min) (point-max))) ! 425: ! 426: (defun TeX-kill-job () ! 427: "Kill the currently running TeX job." ! 428: (interactive) ! 429: (quit-process "TeX-shell" t)) ! 430: ! 431: (defun TeX-recenter-output-buffer (linenum) ! 432: "Redisplay buffer of TeX job output so that most recent output can be seen. ! 433: The last line of the buffer is displayed on ! 434: line LINE of the window, or centered if LINE is nil." ! 435: (interactive "P") ! 436: (let ((tex-shell (get-buffer "*TeX-shell*")) ! 437: (old-buffer (current-buffer))) ! 438: (if (null tex-shell) ! 439: (message "No TeX output buffer") ! 440: (pop-to-buffer tex-shell) ! 441: (bury-buffer tex-shell) ! 442: (goto-char (point-max)) ! 443: (recenter (if linenum ! 444: (prefix-numeric-value linenum) ! 445: (/ (window-height) 2))) ! 446: (pop-to-buffer old-buffer) ! 447: ))) ! 448: ! 449: (defun TeX-print () ! 450: "Print the .dvi file made by \\[TeX-region] or \\[TeX-buffer]. ! 451: Runs the shell command defined by TeX-dvi-print-command." ! 452: (interactive) ! 453: (send-string "TeX-shell" ! 454: (concat TeX-dvi-print-command " \"" TeX-zap-file ".dvi\"\n")) ! 455: (TeX-recenter-output-buffer nil)) ! 456: ! 457: (defun TeX-show-print-queue () ! 458: "Show the print queue that \\[TeX-print] put your job on. ! 459: Runs the shell command defined by TeX-show-queue-command." ! 460: (interactive) ! 461: (if (not (get-buffer "*TeX-shell*")) ! 462: (TeX-start-shell)) ! 463: (send-string "TeX-shell" (concat TeX-show-queue-command "\n")) ! 464: (TeX-recenter-output-buffer nil)) ! 465:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.