aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2000-10-01 00:47:41 +0000
committerStefan Monnier2000-10-01 00:47:41 +0000
commit53c4fe47866097b20949ffc87ed93a6b09387cdf (patch)
tree454769a1c45d12baed8d527fb870d111ac2fcfd9
parenteedd2812657ce6a083c8bc7ee6265e914bad9f69 (diff)
downloademacs-53c4fe47866097b20949ffc87ed93a6b09387cdf.tar.gz
emacs-53c4fe47866097b20949ffc87ed93a6b09387cdf.zip
(latex-metasection-list): New var.
(latex-imenu-create-index): Use it. Move the regexp construction outside loops (and use push). (tex-font-lock-keywords-1, tex-font-lock-keywords-2) (tex-font-lock-keywords): Moved from font-lock.el. (tex-comment-indent): Remove. (tex-common-initialization): Don't set comment-indent-function. (latex-block-default): New var. (tex-latex-block): Use it to provide a default choice. Add any unknown choice to latex-block-names. Insert [...] after {...}. (tex-last-unended-begin): Simplify regexp. (tex-goto-last-unclosed-latex-block, latex-backward-sexp-1) (latex-forward-sexp-1, latex-forward-sexp): New functions. (latex-mode): Set forward-sexp-function.
-rw-r--r--lisp/textmodes/tex-mode.el313
1 files changed, 253 insertions, 60 deletions
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
index 99f0d9d0e93..b66cd6470ab 100644
--- a/lisp/textmodes/tex-mode.el
+++ b/lisp/textmodes/tex-mode.el
@@ -268,6 +268,10 @@ Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].")
268 268
269(defvar tex-mode-syntax-table nil 269(defvar tex-mode-syntax-table nil
270 "Syntax table used while in TeX mode.") 270 "Syntax table used while in TeX mode.")
271
272;;;;
273;;;; Imenu support
274;;;;
271 275
272(defcustom latex-imenu-indent-string ". " 276(defcustom latex-imenu-indent-string ". "
273 "*String to add repeated in front of nested sectional units for Imenu. 277 "*String to add repeated in front of nested sectional units for Imenu.
@@ -281,9 +285,19 @@ An alternative value is \" . \", if you use a font with a narrow period."
281 ("subsubsection" . 4) 285 ("subsubsection" . 4)
282 ("paragraph" . 5) ("subparagraph" . 6))) 286 ("paragraph" . 5) ("subparagraph" . 6)))
283 287
288(defvar latex-metasection-list
289 '("documentstyle" "documentclass"
290 "begin{document}" "end{document}"
291 "appendix" "frontmatter" "mainmatter" "backmatter"))
292
284(defun latex-imenu-create-index () 293(defun latex-imenu-create-index ()
285 "Generates an alist for imenu from a LaTeX buffer." 294 "Generate an alist for imenu from a LaTeX buffer."
286 (let (i0 menu case-fold-search) 295 (let ((section-regexp
296 (concat "\\\\" (regexp-opt (mapcar 'car latex-section-alist) t)
297 "\\*?[ \t]*{"))
298 (metasection-regexp
299 (concat "\\\\" (regexp-opt latex-metasection-list t)))
300 i0 menu case-fold-search)
287 (save-excursion 301 (save-excursion
288 ;; Find the top-most level in this file but don't allow it to be 302 ;; Find the top-most level in this file but don't allow it to be
289 ;; any deeper than "section" (which is top-level in an article). 303 ;; any deeper than "section" (which is top-level in an article).
@@ -296,10 +310,7 @@ An alternative value is \" . \", if you use a font with a narrow period."
296 310
297 ;; Look for chapters and sections. 311 ;; Look for chapters and sections.
298 (goto-char (point-min)) 312 (goto-char (point-min))
299 (while (search-forward-regexp 313 (while (search-forward-regexp section-regexp nil t)
300 (progn
301 (concat "\\\\" (regexp-opt (mapcar 'car latex-section-alist) t)
302 "\\*?[ \t]*{")) nil t)
303 (let ((start (match-beginning 0)) 314 (let ((start (match-beginning 0))
304 (here (point)) 315 (here (point))
305 (i (cdr (assoc (buffer-substring-no-properties 316 (i (cdr (assoc (buffer-substring-no-properties
@@ -326,30 +337,167 @@ An alternative value is \" . \", if you use a font with a narrow period."
326 (goto-char (point-min)) 337 (goto-char (point-min))
327 (while (search-forward-regexp 338 (while (search-forward-regexp
328 "\\\\\\(include\\|input\\|verbatiminput\\|bibliography\\)\ 339 "\\\\\\(include\\|input\\|verbatiminput\\|bibliography\\)\
329[ \t]*{\\([^}\n]+\\)}" 340\[ \t]*{\\([^}\n]+\\)}"
330 nil t) 341 nil t)
331 (setq menu 342 (push (cons (concat "<<" (buffer-substring-no-properties
332 (cons (cons (concat "<<" (buffer-substring-no-properties 343 (match-beginning 2)
333 (match-beginning 2) 344 (match-end 2))
334 (match-end 2)) 345 (if (= (char-after (match-beginning 1)) ?b)
335 (if (= (char-after (match-beginning 1)) ?b) 346 ".bbl"
336 ".bbl" 347 ".tex"))
337 ".tex")) 348 (match-beginning 0))
338 (match-beginning 0)) 349 menu))
339 menu)))
340 350
341 ;; Look for \frontmatter, \mainmatter, \backmatter, and \appendix. 351 ;; Look for \frontmatter, \mainmatter, \backmatter, and \appendix.
342 (goto-char (point-min)) 352 (goto-char (point-min))
343 (while (search-forward-regexp 353 (while (search-forward-regexp metasection-regexp nil t)
344 "\\\\\\(frontmatter\\|mainmatter\\|backmatter\\|appendix\\)\\b" 354 (push (cons "--" (match-beginning 0)) menu))
345 nil t)
346 (setq menu
347 (cons (cons "--" (match-beginning 0))
348 menu)))
349 355
350 ;; Sort in increasing buffer position order. 356 ;; Sort in increasing buffer position order.
351 (sort menu (function (lambda (a b) (< (cdr a) (cdr b)))))))) 357 (sort menu (function (lambda (a b) (< (cdr a) (cdr b))))))))
358
359;;;;
360;;;; Outline support
361;;;;
362
363(defvar latex-outline-regexp
364 (concat "\\\\"
365 (regexp-opt (append latex-metasection-list
366 (mapcar 'car latex-section-alist)) t)))
367
368(defun latex-outline-level ()
369 (if (looking-at latex-outline-regexp)
370 (1+ (or (cdr (assoc (match-string 1) latex-section-alist)) -1))
371 1000))
372
373;;;;
374;;;; Font-Lock support
375;;;;
376
377;(defvar tex-font-lock-keywords
378; ;; Regexps updated with help from Ulrik Dickow <dickow@nbi.dk>.
379; '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}"
380; 2 font-lock-function-name-face)
381; ("\\\\\\(cite\\|label\\|pageref\\|ref\\){\\([^} \t\n]+\\)}"
382; 2 font-lock-constant-face)
383; ;; It seems a bit dubious to use `bold' and `italic' faces since we might
384; ;; not be able to display those fonts.
385; ("{\\\\bf\\([^}]+\\)}" 1 'bold keep)
386; ("{\\\\\\(em\\|it\\|sl\\)\\([^}]+\\)}" 2 'italic keep)
387; ("\\\\\\([a-zA-Z@]+\\|.\\)" . font-lock-keyword-face)
388; ("^[ \t\n]*\\\\def[\\\\@]\\(\\w+\\)" 1 font-lock-function-name-face keep))
389; ;; Rewritten and extended for LaTeX2e by Ulrik Dickow <dickow@nbi.dk>.
390; '(("\\\\\\(begin\\|end\\|newcommand\\){\\([a-zA-Z0-9\\*]+\\)}"
391; 2 font-lock-function-name-face)
392; ("\\\\\\(cite\\|label\\|pageref\\|ref\\){\\([^} \t\n]+\\)}"
393; 2 font-lock-constant-face)
394; ("^[ \t]*\\\\def\\\\\\(\\(\\w\\|@\\)+\\)" 1 font-lock-function-name-face)
395; "\\\\\\([a-zA-Z@]+\\|.\\)"
396; ;; It seems a bit dubious to use `bold' and `italic' faces since we might
397; ;; not be able to display those fonts.
398; ;; LaTeX2e: \emph{This is emphasized}.
399; ("\\\\emph{\\([^}]+\\)}" 1 'italic keep)
400; ;; LaTeX2e: \textbf{This is bold}, \textit{...}, \textsl{...}
401; ("\\\\text\\(\\(bf\\)\\|it\\|sl\\){\\([^}]+\\)}"
402; 3 (if (match-beginning 2) 'bold 'italic) keep)
403; ;; Old-style bf/em/it/sl. Stop at `\\' and un-escaped `&', for tables.
404; ("\\\\\\(\\(bf\\)\\|em\\|it\\|sl\\)\\>\\(\\([^}&\\]\\|\\\\[^\\]\\)+\\)"
405; 3 (if (match-beginning 2) 'bold 'italic) keep))
406
407;; Rewritten with the help of Alexandra Bac <abac@welcome.disi.unige.it>.
408(defconst tex-font-lock-keywords-1
409 (eval-when-compile
410 (let* (;; Names of commands whose arg should be fontified as heading, etc.
411 (headings (regexp-opt
412 '("title" "begin" "end" "chapter" "part"
413 "section" "subsection" "subsubsection"
414 "paragraph" "subparagraph" "subsubparagraph"
415 "newcommand" "renewcommand" "newenvironment"
416 "newtheorem")
417 t))
418 (variables (regexp-opt
419 '("newcounter" "newcounter*" "setcounter" "addtocounter"
420 "setlength" "addtolength" "settowidth")
421 t))
422 (includes (regexp-opt
423 '("input" "include" "includeonly" "bibliography"
424 "epsfig" "psfig" "epsf" "nofiles" "usepackage"
425 "includegraphics" "includegraphics*")
426 t))
427 ;; Miscellany.
428 (slash "\\\\")
429 (opt "\\(\\[[^]]*\\]\\)?")
430 (arg "{\\(\\(?:[^{}]+\\(?:{[^}]*}\\)?\\)+\\)"))
431 (list
432 ;; Heading args.
433 (list (concat slash headings "\\*?" opt arg)
434 3 'font-lock-function-name-face 'prepend)
435 ;; Variable args.
436 (list (concat slash variables arg) 2 'font-lock-variable-name-face)
437 ;; Include args.
438 (list (concat slash includes opt arg) 3 'font-lock-builtin-face)
439 ;; Definitions. I think.
440 '("^[ \t]*\\\\def\\\\\\(\\(\\w\\|@\\)+\\)"
441 1 font-lock-function-name-face)
442 )))
443 "Subdued expressions to highlight in TeX modes.")
444
445(defconst tex-font-lock-keywords-2
446 (append tex-font-lock-keywords-1
447 (eval-when-compile
448 (let* (;;
449 ;; Names of commands whose arg should be fontified with fonts.
450 (bold (regexp-opt '("bf" "textbf" "textsc" "textup"
451 "boldsymbol" "pmb") t))
452 (italic (regexp-opt '("it" "textit" "textsl" "emph") t))
453 (type (regexp-opt '("texttt" "textmd" "textrm" "textsf") t))
454 ;;
455 ;; Names of commands whose arg should be fontified as a citation.
456 (citations (regexp-opt
457 '("label" "ref" "pageref" "vref" "eqref"
458 "cite" "nocite" "caption" "index" "glossary"
459 "footnote" "footnotemark" "footnotetext")
460 t))
461 ;;
462 ;; Names of commands that should be fontified.
463 (specials (regexp-opt
464 '("\\"
465 "linebreak" "nolinebreak" "pagebreak" "nopagebreak"
466 "newline" "newpage" "clearpage" "cleardoublepage"
467 "displaybreak" "allowdisplaybreaks" "enlargethispage")
468 t))
469 (general "\\([a-zA-Z@]+\\**\\|[^ \t\n]\\)")
470 ;;
471 ;; Miscellany.
472 (slash "\\\\")
473 (opt "\\(\\[[^]]*\\]\\)?")
474 (arg "{\\(\\(?:[^{}]+\\(?:{[^}]*}\\)?\\)+\\)"))
475 (list
476 ;;
477 ;; Citation args.
478 (list (concat slash citations opt arg) 3 'font-lock-constant-face)
479 ;;
480 ;; Command names, special and general.
481 (cons (concat slash specials) 'font-lock-warning-face)
482 (concat slash general)
483 ;;
484 ;; Font environments. It seems a bit dubious to use `bold' etc. faces
485 ;; since we might not be able to display those fonts.
486 (list (concat slash bold arg) 2 '(quote bold) 'append)
487 (list (concat slash italic arg) 2 '(quote italic) 'append)
488 (list (concat slash type arg) 2 '(quote bold-italic) 'append)
489 ;;
490 ;; Old-style bf/em/it/sl. Stop at `\\' and un-escaped `&', for tables.
491 (list (concat "\\\\\\(\\(bf\\)\\|em\\|it\\|sl\\)\\>"
492 "\\(\\([^}&\\]\\|\\\\[^\\]\\)+\\)")
493 3 '(if (match-beginning 2) 'bold 'italic) 'append)
494 ))))
495 "Gaudy expressions to highlight in TeX modes.")
496
497(defvar tex-font-lock-keywords tex-font-lock-keywords-1
498 "Default expressions to highlight in TeX modes.")
352 499
500
353(defun tex-define-common-keys (keymap) 501(defun tex-define-common-keys (keymap)
354 "Define the keys that we want defined both in TeX mode and in the TeX shell." 502 "Define the keys that we want defined both in TeX mode and in the TeX shell."
355 (define-key keymap "\C-c\C-k" 'tex-kill-job) 503 (define-key keymap "\C-c\C-k" 'tex-kill-job)
@@ -592,6 +740,7 @@ subshell is initiated, `tex-shell-hook' is run."
592 'latex-fill-nobreak-predicate) 740 'latex-fill-nobreak-predicate)
593 (set (make-local-variable 'outline-regexp) latex-outline-regexp) 741 (set (make-local-variable 'outline-regexp) latex-outline-regexp)
594 (set (make-local-variable 'outline-level) 'latex-outline-level) 742 (set (make-local-variable 'outline-level) 'latex-outline-level)
743 (set (make-local-variable 'forward-sexp-function) 'latex-forward-sexp)
595 (run-hooks 'tex-mode-hook)) 744 (run-hooks 'tex-mode-hook))
596 745
597;;;###autoload 746;;;###autoload
@@ -676,7 +825,6 @@ Entering SliTeX mode runs the hook `text-mode-hook', then the hook
676 (set (make-local-variable 'comment-add) 1) 825 (set (make-local-variable 'comment-add) 1)
677 (set (make-local-variable 'comment-start-skip) 826 (set (make-local-variable 'comment-start-skip)
678 "\\(\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)") 827 "\\(\\(^\\|[^\\]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)")
679 (set (make-local-variable 'comment-indent-function) 'tex-comment-indent)
680 (set (make-local-variable 'parse-sexp-ignore-comments) t) 828 (set (make-local-variable 'parse-sexp-ignore-comments) t)
681 (set (make-local-variable 'compare-windows-whitespace) 829 (set (make-local-variable 'compare-windows-whitespace)
682 'tex-categorize-whitespace) 830 'tex-categorize-whitespace)
@@ -699,13 +847,6 @@ Entering SliTeX mode runs the hook `text-mode-hook', then the hook
699 (make-local-variable 'tex-end-of-header) 847 (make-local-variable 'tex-end-of-header)
700 (make-local-variable 'tex-trailer)) 848 (make-local-variable 'tex-trailer))
701 849
702(defun tex-comment-indent ()
703 (if (looking-at "%%%")
704 (current-column)
705 (skip-chars-backward " \t")
706 (max (if (bolp) 0 (1+ (current-column)))
707 comment-column)))
708
709(defun tex-categorize-whitespace (backward-limit) 850(defun tex-categorize-whitespace (backward-limit)
710 ;; compare-windows-whitespace is set to this. 851 ;; compare-windows-whitespace is set to this.
711 ;; This is basically a finite-state machine. 852 ;; This is basically a finite-state machine.
@@ -895,28 +1036,46 @@ A prefix arg inhibits the checking."
895 (setq inside t))))) 1036 (setq inside t)))))
896 inside)) 1037 inside))
897 1038
1039(defvar latex-block-default "enumerate")
1040
898;;; Like tex-insert-braces, but for LaTeX. 1041;;; Like tex-insert-braces, but for LaTeX.
899(define-skeleton tex-latex-block 1042(define-skeleton tex-latex-block
900 "Create a matching pair of lines \\begin[OPT]{NAME} and \\end{NAME} at point. 1043 "Create a matching pair of lines \\begin[OPT]{NAME} and \\end{NAME} at point.
901Puts point on a blank line between them." 1044Puts point on a blank line between them."
902 (completing-read "LaTeX block name: " 1045 (let ((choice (completing-read (format "LaTeX block name [%s]: "
903 (mapcar 'list 1046 latex-block-default)
904 (append standard-latex-block-names 1047 (mapcar 'list
905 latex-block-names))) 1048 (append standard-latex-block-names
906 "\\begin[" 1049 latex-block-names))
907 (skeleton-read "[options]: ") & ?\] | -1 1050 nil nil nil nil latex-block-default)))
908 ?\{ 1051 (setq latex-block-default choice)
909 str 1052 (unless (or (member choice standard-latex-block-names)
910 ?\} \n 1053 (member choice latex-block-names))
911 _ \n 1054 ;; Remember new block names for later completion.
912 "\\end{" str ?\}) 1055 (push choice latex-block-names))
1056 choice)
1057 "\\begin{" str ?\}
1058 ?\[ (skeleton-read "[options]: ") & ?\] | -1
1059 \n _ \n
1060 "\\end{" str ?\} >)
1061
1062
1063;;;;
1064;;;; LaTeX syntax navigation
1065;;;;
913 1066
914(defun tex-last-unended-begin () 1067(defun tex-last-unended-begin ()
915 "Leave point at the beginning of the last `\\begin{...}' that is unended." 1068 "Leave point at the beginning of the last `\\begin{...}' that is unended."
916 (while (and (re-search-backward "\\(\\\\begin\\s *{\\)\\|\\(\\\\end\\s *{\\)") 1069 (while (and (re-search-backward "\\\\\\(begin\\|end\\)\\s *{")
917 (looking-at "\\\\end{")) 1070 (looking-at "\\\\end"))
918 (tex-last-unended-begin))) 1071 (tex-last-unended-begin)))
919 1072
1073(defun tex-next-unmatched-end ()
1074 "Leave point at the end of the next `\\end' that is unended."
1075 (while (and (re-search-forward "\\\\\\(begin\\|end\\)\\s *{[^}]+}")
1076 (looking-at "\\\\begin"))
1077 (tex-next-unmatched-end)))
1078
920(defun tex-goto-last-unclosed-latex-block () 1079(defun tex-goto-last-unclosed-latex-block ()
921 "Move point to the last unclosed \\begin{...}. 1080 "Move point to the last unclosed \\begin{...}.
922Mark is left at original location." 1081Mark is left at original location."
@@ -930,6 +1089,57 @@ Mark is left at original location."
930 (push-mark) 1089 (push-mark)
931 (goto-char spot))) 1090 (goto-char spot)))
932 1091
1092(defun latex-backward-sexp-1 ()
1093 "Like (backward-sexp 1) but aware of multi-char elements."
1094 (let ((pos (point))
1095 (forward-sexp-function))
1096 (backward-sexp 1)
1097 (if (looking-at "\\\\begin\\>")
1098 (signal 'scan-error
1099 (list "Containing expression ends prematurely"
1100 (point) (prog1 (point) (goto-char pos))))
1101 (when (eq (char-after) ?{)
1102 (let ((newpos (point)))
1103 (when (ignore-errors (backward-sexp 1) t)
1104 (if (looking-at "\\\\end\\>")
1105 (tex-last-unended-begin)
1106 (goto-char newpos))))))))
1107
1108(defun latex-forward-sexp-1 ()
1109 "Like (forward-sexp 1) but aware of multi-char elements."
1110 (let ((pos (point))
1111 (forward-sexp-function))
1112 (forward-sexp 1)
1113 (let ((newpos (point)))
1114 (skip-syntax-backward "/w")
1115 (cond
1116 ((looking-at "\\\\end\\>")
1117 (signal 'scan-error
1118 (list "Containing expression ends prematurely"
1119 (point)
1120 (prog1
1121 (progn (ignore-errors (forward-sexp 2)) (point))
1122 (goto-char pos)))))
1123 ((looking-at "\\\\begin\\>")
1124 (goto-char (match-end 0))
1125 (tex-next-unmatched-end))
1126 (t (goto-char newpos))))))
1127
1128(defun latex-forward-sexp (&optional arg)
1129 "Like `forward-sexp' but aware of multi-char elements."
1130 (interactive "P")
1131 (unless arg (setq arg 1))
1132 (let ((pos (point)))
1133 (condition-case err
1134 (while (/= arg 0)
1135 (setq arg
1136 (if (> arg 0)
1137 (progn (latex-forward-sexp-1) (1- arg))
1138 (progn (latex-backward-sexp-1) (1+ arg)))))
1139 (scan-error
1140 (goto-char pos)
1141 (signal (car err) (cdr err))))))
1142
933(defun tex-close-latex-block () 1143(defun tex-close-latex-block ()
934 "Creates an \\end{...} to match the last unclosed \\begin{...}." 1144 "Creates an \\end{...} to match the last unclosed \\begin{...}."
935 (interactive "*") 1145 (interactive "*")
@@ -1461,23 +1671,6 @@ Runs the shell command defined by `tex-show-queue-command'."
1461 (tex-send-command tex-bibtex-command tex-out-file)) 1671 (tex-send-command tex-bibtex-command tex-out-file))
1462 (tex-display-shell)) 1672 (tex-display-shell))
1463 1673
1464;;;;
1465;;;; Outline support
1466;;;;
1467
1468(defvar latex-outline-regexp
1469 (concat "\\\\"
1470 (regexp-opt (nconc (list "documentstyle" "documentclass"
1471 "begin{document}" "end{document}"
1472 "appendix")
1473 (mapcar 'car latex-section-alist)) t)))
1474
1475(defun latex-outline-level ()
1476 (if (looking-at latex-outline-regexp)
1477 (1+ (or (cdr (assoc (match-string 1) latex-section-alist)) -1))
1478 1000))
1479
1480
1481(run-hooks 'tex-mode-load-hook) 1674(run-hooks 'tex-mode-load-hook)
1482 1675
1483(provide 'tex-mode) 1676(provide 'tex-mode)