Annotation of GNUtools/emacs/lisp/tex-mode.el, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.