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