Mercurial > emacs
changeset 32479:783ed0889617
Require CL when compiling.
(tex-mode-syntax-table): Init immediately.
(tex-mode-map): Bind M-RET to latex-insert-item.
(latex-mode): Set indent-line-function to latex-indent.
(tex-common-initialization): Don't setup the syntax-table any more.
(latex-insert-item): New skeleton.
(tex-next-unmatched-end): Fix copy/paste braino.
(latex-syntax-after, latex-skip-close-parens, latex-down-list)
(latex-indent, latex-find-indent): New functions.
(tex-indent-allhanging, tex-indent-arg, tex-latex-indent-syntax-table)
(tex-indent-item, tex-indent-item-re, tex-indent-basic): New vars.
(tex-compilation-parse-errors): Use with-syntax-table.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Sun, 15 Oct 2000 03:48:17 +0000 |
parents | a7703eb49693 |
children | 261dcd5e9f0a |
files | lisp/textmodes/tex-mode.el |
diffstat | 1 files changed, 150 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
--- a/lisp/textmodes/tex-mode.el Sun Oct 15 03:34:18 2000 +0000 +++ b/lisp/textmodes/tex-mode.el Sun Oct 15 03:48:17 2000 +0000 @@ -31,6 +31,7 @@ ;; Pacify the byte-compiler (eval-when-compile (require 'compare-w) + (require 'cl) (require 'skeleton)) (require 'shell) @@ -266,7 +267,21 @@ "File name that \\[tex-print] prints. Set by \\[tex-region], \\[tex-buffer], and \\[tex-file].") -(defvar tex-mode-syntax-table nil +(easy-mmode-defsyntax tex-mode-syntax-table + '((?% . "<") + (?\n . ">") + (?\f . ">") + (?\C-@ . "w") + (?' . "w") + (?@ . "_") + (?* . "_") + (?\t . " ") + (?~ . " ") + (?$ . "$$") + (?\\ . "/") + (?\" . ".") + (?& . ".") + (?_ . ".")) "Syntax table used while in TeX mode.") ;;;; @@ -527,6 +542,7 @@ (tex-define-common-keys tex-mode-map) (define-key tex-mode-map "\"" 'tex-insert-quote) (define-key tex-mode-map "\n" 'tex-terminate-paragraph) + (define-key tex-mode-map "\M-\r" 'latex-insert-item) (define-key tex-mode-map "\C-c}" 'up-list) (define-key tex-mode-map "\C-c{" 'tex-insert-braces) (define-key tex-mode-map "\C-c\C-r" 'tex-region) @@ -738,6 +754,7 @@ (set (make-local-variable 'tex-face-alist) tex-latex-face-alist) (set (make-local-variable 'fill-nobreak-predicate) 'latex-fill-nobreak-predicate) + (set (make-local-variable 'indent-line-function) 'latex-indent) (set (make-local-variable 'outline-regexp) latex-outline-regexp) (set (make-local-variable 'outline-level) 'latex-outline-level) (set (make-local-variable 'forward-sexp-function) 'latex-forward-sexp) @@ -790,28 +807,7 @@ (defun tex-common-initialization () (use-local-map tex-mode-map) - (setq local-abbrev-table text-mode-abbrev-table) - (if (null tex-mode-syntax-table) - (let ((char 0)) - (setq tex-mode-syntax-table (make-syntax-table)) - (set-syntax-table tex-mode-syntax-table) - (while (< char ? ) - (modify-syntax-entry char ".") - (setq char (1+ char))) - (modify-syntax-entry ?\C-@ "w") - (modify-syntax-entry ?\t " ") - (modify-syntax-entry ?\n ">") - (modify-syntax-entry ?\f ">") - (modify-syntax-entry ?$ "$$") - (modify-syntax-entry ?% "<") - (modify-syntax-entry ?\\ "/") - (modify-syntax-entry ?\" ".") - (modify-syntax-entry ?& ".") - (modify-syntax-entry ?_ ".") - (modify-syntax-entry ?@ "_") - (modify-syntax-entry ?~ " ") - (modify-syntax-entry ?' "w")) - (set-syntax-table tex-mode-syntax-table)) + (set-syntax-table tex-mode-syntax-table) ;; Regexp isearch should accept newline and formfeed as whitespace. (set (make-local-variable 'search-whitespace-regexp) "[ \t\r\n\f]+") ;; A line containing just $$ is treated as a paragraph separator. @@ -1059,6 +1055,11 @@ \n _ \n "\\end{" str ?\} >) +(define-skeleton latex-insert-item + "Insert a \item macro." + nil + \n "\\item " >) + ;;;; ;;;; LaTeX syntax navigation @@ -1073,7 +1074,8 @@ (defun tex-next-unmatched-end () "Leave point at the end of the next `\\end' that is unended." (while (and (re-search-forward "\\\\\\(begin\\|end\\)\\s *{[^}]+}") - (looking-at "\\\\begin")) + (save-excursion (goto-char (match-beginning 0)) + (looking-at "\\\\begin"))) (tex-next-unmatched-end))) (defun tex-goto-last-unclosed-latex-block () @@ -1140,6 +1142,27 @@ (goto-char pos) (signal (car err) (cdr err)))))) +(defun latex-syntax-after () + "Like (char-syntax (char-after)) but aware of multi-char elements." + (if (looking-at "\\\\end\\>") ?\) (char-syntax (char-after)))) + +(defun latex-skip-close-parens () + "Like (skip-syntax-forward \" )\") but aware of multi-char elements." + (let ((forward-sexp-function nil)) + (while (progn (skip-syntax-forward " )") + (looking-at "\\\\end\\>")) + (forward-sexp 2)))) + +(defun latex-down-list () + "Like (down-list 1) but aware of multi-char elements." + (forward-comment (point-max)) + (let ((forward-sexp-function nil)) + (if (not (looking-at "\\\\begin\\>")) + (down-list 1) + (forward-sexp 1) + ;; Skip arguments. + (while (looking-at "[ \t]*\\s(") (forward-sexp))))) + (defun tex-close-latex-block () "Creates an \\end{...} to match the last unclosed \\begin{...}." (interactive "*") @@ -1354,18 +1377,14 @@ (error-text (regexp-quote (match-string 3))) (filename (save-excursion - (unwind-protect - (progn - (set-syntax-table tex-error-parse-syntax-table) - (backward-up-list 1) - (skip-syntax-forward "(_") - (while (not (file-readable-p - (thing-at-point 'filename))) - (skip-syntax-backward "(_") - (backward-up-list 1) - (skip-syntax-forward "(_")) - (thing-at-point 'filename)) - (set-syntax-table old-syntax-table)))) + (with-syntax-table tex-error-parse-syntax-table + (backward-up-list 1) + (skip-syntax-forward "(_") + (while (not (file-readable-p (thing-at-point 'filename))) + (skip-syntax-backward "(_") + (backward-up-list 1) + (skip-syntax-forward "(_")) + (thing-at-point 'filename)))) (new-file (or (null last-filename) (not (string-equal last-filename filename)))) @@ -1670,6 +1689,101 @@ (tex-send-command tex-shell-cd-command file-dir) (tex-send-command tex-bibtex-command tex-out-file)) (tex-display-shell)) + +;;;; +;;;; LaTeX indentation +;;;; + +(defvar tex-indent-allhanging t) +(defvar tex-indent-arg 4) +(defvar tex-indent-basic 2) +(defvar tex-indent-item tex-indent-basic) +(defvar tex-indent-item-re "\\\\\\(bib\\)?item\\>") + +(easy-mmode-defsyntax tex-latex-indent-syntax-table + '((?$ . ".")) + "Syntax table used while computing indentation." + :copy tex-mode-syntax-table) + +(defun latex-indent (&optional arg) + (with-syntax-table tex-latex-indent-syntax-table + ;; TODO: Rather than ignore $, we should try to be more clever about it. + (let ((indent + (save-excursion + (beginning-of-line) + (latex-find-indent)))) + (if (< indent 0) (setq indent 0)) + (if (<= (current-column) (current-indentation)) + (indent-line-to indent) + (save-excursion (indent-line-to indent)))))) + +(defun latex-find-indent (&optional virtual) + "Find the proper indentation of text after point. +VIRTUAL if non-nil indicates that we're only trying to find the indentation + in order to determine the indentation of something else. +There might be text before point." + (save-excursion + (skip-chars-forward " \t") + (or + ;; Trust the current indentation, if such info is applicable. + (and virtual (>= (current-indentation) (current-column)) + (current-indentation)) + ;; Put leading close-paren where the matching open brace would be. + (and (eq (latex-syntax-after) ?\)) + (ignore-errors + (save-excursion + (latex-skip-close-parens) + (latex-backward-sexp-1) + (latex-find-indent 'virtual)))) + ;; Default (maybe an argument) + (let ((pos (point)) + (char (char-after)) + ;; Outdent \item if necessary. + (indent (if (looking-at tex-indent-item-re) (- tex-indent-item) 0)) + up-list-pos) + ;; Find the previous point which determines our current indentation. + (condition-case err + (progn + (latex-backward-sexp-1) + (while (> (current-column) (current-indentation)) + (latex-backward-sexp-1))) + (scan-error + (setq up-list-pos (nth 2 err)))) + (if (integerp up-list-pos) + ;; Have to indent relative to the open-paren. + (progn + (goto-char up-list-pos) + (if (and (not tex-indent-allhanging) + (> pos (progn (latex-down-list) + (forward-comment (point-max)) + (point)))) + ;; Align with the first element after the open-paren. + (current-column) + ;; We're the first element after a hanging brace. + (goto-char up-list-pos) + (+ indent tex-indent-basic (latex-find-indent 'virtual)))) + ;; We're now at the beginning of a line. + (if (not (and (not virtual) (eq (char-after) ?\\))) + ;; Nothing particular here: just keep the same indentation. + (+ indent (current-column)) + ;; We're now looking at a macro call. + (if (looking-at tex-indent-item-re) + ;; Indenting relative to an item, have to re-add the outdenting. + (+ indent (current-column) tex-indent-item) + (let ((col (current-column))) + (if (not (eq (char-syntax char) ?\()) + ;; If the first char was not an open-paren, there's + ;; a risk that this is really not an argument to the + ;; macro at all. + (+ indent col) + (forward-sexp 1) + (if (< (line-end-position) + (save-excursion (forward-comment (point-max)) + (point))) + ;; we're indenting the first argument. + (min (current-column) (+ tex-indent-arg col)) + (skip-syntax-forward " ") + (current-column))))))))))) (run-hooks 'tex-mode-load-hook)