Annotation of GNUtools/emacs/lisp/tex-mode.el, revision 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.