Annotation of 43BSDReno/contrib/emacs-18.55/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 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: 

unix.superglobalmegacorp.com

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