[comp.emacs] Closing LaTeX blocks

ram-ashwin@YALE.ARPA (Ashwin Ram) (02/23/88)

Does anyone have code that recognizes "\begin{foo} ... \end{foo}" pairs in a
LaTeX file as a "balanced pair"?  In particular, I'm looking for something
that would validate a buffer, indicate a mismatch (just as for different
kinds of parens), and insert the correct \end{...} expression upon hitting a
key, depending on the current \begin{...} expression that you're in?  I have
code that just searches back to the previous \begin{...} expression, which is
nicer than the default TeX-close-LaTeX-block function but still a long way
from knowing about \begin{...}'s that have already been \end'ed.

Ideally, "\begin{foo}" and "\end{foo}" should behave like a parenthesis pair.
If you have code that does this, could you please e-mail it to me or post it
to comp.emacs?

Thanks.

-- Ashwin.

ARPA:    Ram-Ashwin@cs.yale.edu
UUCP:    {decvax,ucbvax,harvard,cmcl2,...}!yale!Ram-Ashwin
BITNET:  Ram@yalecs

metz@iam.unibe.ch (Igor Metz) (02/23/88)

A set of macros that could solve your problem can be found in the VorTeX
distribution. Here is the original message I got from the VorTeX project:

    From:    The VorTeX Distribution <vortex@ucbarpa.berkeley.edu>
    To:      <metz@iam.unibe.ch>
    Subject: Re: Vortex


    Thank you for your interest in VorTeX.  The following is a list of the
    utilities included in the distribution, with a short description of each:

    dvitool - A previewer for DVI files which runs on the SUN workstation.
    dvi2x   - A previewer for DVI files which uses an X display server.
    fonts   - A set of fonts used for TeX and LaTeX in the sizes
	      needed for using the previewer.
    pxltool - SUN-based font editor for PXL files
    emacs   - A large LISP library for use with emacs which facilitates 
	      editing of TeX, LaTeX, and BIBTex files.
    dvitoip - A DVI to INTERPRESS filter.  It allows the printing of DVI files
	      on an Xerox Dandelion printer.
    texdvi  - A program which runs TeX, LaTeX, or SliTeX and previews
	      the results using DVItool.
    gr2ps   - A program which converts grelim files to POSTSCRIPT.
    makeindex - A general purpose index generator for use with LaTeX files.
		May also be used with other dialects of TeX.
		Includes patches to work under VMS.


    We have sent a licensing package to the postal address you provided.  This
    package contains further information about VorTeX, information about
    licensing procedures, and the appropriate forms for licensing VorTeX.

			       Sincerely,
			       Peter Vukovich
			       VorTeX group, Univerity of California, Berkeley



    Please address any correspondence to:

    Professor Michael A. Harrison
    Att. Vortex Dist.
    Computer Science Division
    University of California
    Berkeley, CA 94720


    UUCP: ...!ucbvax!dist-vortex
    ARPA: dist-vortex@ucbvax.berkeley.edu

Regards,

Igor Metz                    X400: metz@iam.unibe.ch or metz@iam.unibe.chunet
Institut fuer Informatik     ARPA: metz%iam.unibe.ch@relay.cs.net
und angewandte Mathematik    UUCP: ..!uunet!mcvax!iam.unibe.ch!metz
Universitaet Bern
Switzerland		     Phone: (+31) 65 49 02

Ram-Ashwin@YALE.ARPA (Ashwin Ram) (03/04/88)

In article <8802230342.AA12720@ATHENA.CS.YALE.EDU>, ram-ashwin@YALE (Ashwin Ram) writes:
> Does anyone have code that recognizes "\begin{foo} ... \end{foo}" pairs in a
> LaTeX file as a "balanced pair"?  In particular, I'm looking for something
> that would validate a buffer, indicate a mismatch (just as for different
> kinds of parens), and insert the correct \end{...} expression upon hitting a
> key, depending on the current \begin{...} expression that you're in?

I got several useful replies to this (thanks, guys!), including a couple of
fairly elaborate latex-modes.  I also got some requests to forward my final
solution, so here goes.  (I should add that I got a couple of nicer solutions
than this in response to my request.  This is just the simplest and least
elaborate fix that works, which you can install in a couple of minutes, so I
decided to share it with the net.)

The easiest solution is to redefine TeX-close-LaTeX-block (in the file
lisp/tex-mode.el).  Just replace it with the following function (which is
already bound to C-c C-f by default).  [I suggest that this be replaced in
the GNU Emacs distribution since it's a lot nicer than the old function.]

----------------------------------------------------------------------------
;; Replacement for TeX-close-LaTeX-block in lisp/tex-mode.el.
;; Ashwin Ram, 2/22/88.
(defun TeX-close-LaTeX-block (&optional validate)
   "Inserts an \\end{...} to match corresponding \\begin{...}.
If optional argument VALIDATE is t, doesn't insert anything, only validates."
   (interactive "*")
   (let ((fail-point (point))
         (nesting '())
         (done nil))         
      (end-of-line)
      (while (not done)
         (if (re-search-backward "\\\\\\(begin\\|end\\){\\([^}\n]*\\)}" (point-min) t)
             (let ((which (buffer-substring (match-beginning 1) (match-end 1)))
                   (text (buffer-substring (match-beginning 2) (match-end 2))))
                (if (equal which "end")
                    (setq nesting (cons text nesting))
                    (if (null nesting)
                        (let ((indentation (current-column)))
                           (goto-char fail-point)
                           (if validate
                               (error "\\begin{%s} is never ended" text)
                               (progn
                                  (beginning-of-line)
                                  (if (not (looking-at "^[ \t]*\n"))
                                      (progn (end-of-line) (insert "\n")))
                                  (indent-to indentation)
                                  (insert "\\end{" text "}\n")))
                           (setq done t))
                        (if (equal text (car nesting))
                            (setq nesting (cdr nesting))
                            (error "\\begin{%s} ended by \\end{%s}" text (car nesting))))))
             (progn
                (goto-char fail-point)
                (if (not validate) (message "No unmatched \\begin{...} to end here"))
                (setq done t))))))
----------------------------------------------------------------------------

To do begin-end checking in addition to {} checking, I changed the following
function by adding a couple of lines to call the above.  This is less than
ideal, I suppose, but it works.  The lines are initialled.

----------------------------------------------------------------------------
(defun TeX-validate-paragraph (start end)
  (condition-case ()
      (save-excursion
	(save-restriction
	  (narrow-to-region start end)
          (goto-char end)           ;; Added, AR 2/22/88.
          (TeX-close-LaTeX-block t) ;; Added, AR 2/22/88.
	  (goto-char start)
	  (forward-sexp (- end start))
	  t))
    (error nil)))
----------------------------------------------------------------------------

-- Ashwin Ram --

ARPA:    Ram-Ashwin@cs.yale.edu
UUCP:    {decvax,ucbvax,harvard,cmcl2,...}!yale!Ram-Ashwin
BITNET:  Ram@yalecs