;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands -*- coding: utf-8 -*-
-;; Copyright (C) 1985-1986, 1989, 1992, 1994-1999, 2001-2012
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1989, 1992, 1994-1999, 2001-2013 Free
+;; Software Foundation, Inc.
;; Maintainer: FSF
;; Keywords: tex
;; Pacify the byte-compiler
(eval-when-compile
(require 'compare-w)
- (require 'cl)
+ (require 'cl-lib)
(require 'skeleton))
(defvar font-lock-comment-face)
tex shell terminates.")
(defvar tex-command "tex"
- "*Command to run TeX.
+ "Command to run TeX.
If this string contains an asterisk \(`*'\), that is replaced by the file name;
otherwise the value of `tex-start-options', the \(shell-quoted\)
value of `tex-start-commands', and the file name are added at the end
(if (looking-at latex-outline-regexp)
(1+ (or (cdr (assoc (match-string 1) latex-section-alist)) -1))
1000))
+
+(defun tex-current-defun-name ()
+ "Return the name of the TeX section/paragraph/chapter at point, or nil."
+ (save-excursion
+ (when (re-search-backward
+ "\\\\\\(sub\\)*\\(section\\|paragraph\\|chapter\\)"
+ nil t)
+ (goto-char (match-beginning 0))
+ (buffer-substring-no-properties
+ (1+ (point)) ; without initial backslash
+ (line-end-position)))))
\f
;;;;
;;;; Font-Lock support
'("input" "include" "includeonly" "bibliography"
"epsfig" "psfig" "epsf" "nofiles" "usepackage"
"documentstyle" "documentclass" "verbatiminput"
- "includegraphics" "includegraphics*"
- "url" "nolinkurl")
+ "includegraphics" "includegraphics*")
t))
+ (verbish (regexp-opt '("url" "nolinkurl" "path") t))
;; Miscellany.
(slash "\\\\")
(opt " *\\(\\[[^]]*\\] *\\)*")
;; This would allow highlighting \newcommand\CMD but requires
;; adapting subgroup numbers below.
;; (arg "\\(?:{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)\\|\\\\[a-z*]+\\)"))
- (arg "{\\(\\(?:[^{}\\]+\\|\\\\.\\|{[^}]*}\\)+\\)"))
- (list
- ;; display $$ math $$
- ;; We only mark the match between $$ and $$ because the $$ delimiters
- ;; themselves have already been marked (along with $..$) by syntactic
- ;; fontification. Also this is done at the very beginning so as to
- ;; interact with the other keywords in the same way as $...$ does.
- (list "\\$\\$\\([^$]+\\)\\$\\$" 1 'tex-math-face)
- ;; Heading args.
- (list (concat slash headings "\\*?" opt arg)
- ;; If ARG ends up matching too much (if the {} don't match, e.g.)
- ;; jit-lock will do funny things: when updating the buffer
- ;; the re-highlighting is only done locally so it will just
- ;; match the local line, but defer-contextually will
- ;; match more lines at a time, so ARG will end up matching
- ;; a lot more, which might suddenly include a comment
- ;; so you get things highlighted bold when you type them
- ;; but they get turned back to normal a little while later
- ;; because "there's already a face there".
- ;; Using `keep' works around this un-intuitive behavior as well
- ;; as improves the behavior in the very rare case where you do
- ;; have a comment in ARG.
- 3 'font-lock-function-name-face 'keep)
- (list (concat slash "\\(?:provide\\|\\(?:re\\)?new\\)command\\** *\\(\\\\[A-Za-z@]+\\)")
- 1 'font-lock-function-name-face 'keep)
- ;; Variable args.
- (list (concat slash variables " *" arg) 2 'font-lock-variable-name-face)
- ;; Include args.
- (list (concat slash includes opt arg) 3 'font-lock-builtin-face)
- ;; Definitions. I think.
- '("^[ \t]*\\\\def *\\\\\\(\\(\\w\\|@\\)+\\)"
+ (inbraces-re (lambda (re)
+ (concat "\\(?:[^{}\\]\\|\\\\.\\|" re "\\)")))
+ (arg (concat "{\\(" (funcall inbraces-re "{[^}]*}") "+\\)")))
+ `( ;; Highlight $$math$$ and $math$.
+ ;; This is done at the very beginning so as to interact with the other
+ ;; keywords in the same way as comments and strings.
+ (,(concat "\\$\\$?\\(?:[^$\\{}]\\|\\\\.\\|{"
+ (funcall inbraces-re
+ (concat "{" (funcall inbraces-re "{[^}]*}") "*}"))
+ "*}\\)+\\$?\\$")
+ (0 tex-math-face))
+ ;; Heading args.
+ (,(concat slash headings "\\*?" opt arg)
+ ;; If ARG ends up matching too much (if the {} don't match, e.g.)
+ ;; jit-lock will do funny things: when updating the buffer
+ ;; the re-highlighting is only done locally so it will just
+ ;; match the local line, but defer-contextually will
+ ;; match more lines at a time, so ARG will end up matching
+ ;; a lot more, which might suddenly include a comment
+ ;; so you get things highlighted bold when you type them
+ ;; but they get turned back to normal a little while later
+ ;; because "there's already a face there".
+ ;; Using `keep' works around this un-intuitive behavior as well
+ ;; as improves the behavior in the very rare case where you do
+ ;; have a comment in ARG.
+ 3 font-lock-function-name-face keep)
+ (,(concat slash "\\(?:provide\\|\\(?:re\\)?new\\)command\\** *\\(\\\\[A-Za-z@]+\\)")
+ 1 font-lock-function-name-face keep)
+ ;; Variable args.
+ (,(concat slash variables " *" arg) 2 font-lock-variable-name-face)
+ ;; Include args.
+ (,(concat slash includes opt arg) 3 font-lock-builtin-face)
+ ;; Verbatim-like args.
+ (,(concat slash verbish opt arg) 3 'tex-verbatim)
+ ;; Definitions. I think.
+ ("^[ \t]*\\\\def *\\\\\\(\\(\\w\\|@\\)+\\)"
1 font-lock-function-name-face))))
"Subdued expressions to highlight in TeX modes.")
(1 (tex-font-lock-suscript (match-beginning 0)) append))))
"Experimental expressions to highlight in TeX modes.")
-(defvar tex-font-lock-keywords tex-font-lock-keywords-1
+(defconst tex-font-lock-keywords tex-font-lock-keywords-1
"Default expressions to highlight in TeX modes.")
(defvar tex-verbatim-environments
(set-keymap-parent map text-mode-map)
(tex-define-common-keys map)
(define-key map "\"" 'tex-insert-quote)
- (define-key map "(" 'skeleton-pair-insert-maybe)
- (define-key map "{" 'skeleton-pair-insert-maybe)
- (define-key map "[" 'skeleton-pair-insert-maybe)
- (define-key map "$" 'skeleton-pair-insert-maybe)
(define-key map "\n" 'tex-terminate-paragraph)
(define-key map "\M-\r" 'latex-insert-item)
(define-key map "\C-c}" 'up-list)
Entering Plain-tex mode runs the hook `text-mode-hook', then the hook
`tex-mode-hook', and finally the hook `plain-tex-mode-hook'. When the
special subshell is initiated, the hook `tex-shell-hook' is run."
- (set (make-local-variable 'tex-command) tex-run-command)
- (set (make-local-variable 'tex-start-of-header) "%\\*\\*start of header")
- (set (make-local-variable 'tex-end-of-header) "%\\*\\*end of header")
- (set (make-local-variable 'tex-trailer) "\\bye\n"))
+ (setq-local tex-command tex-run-command)
+ (setq-local tex-start-of-header "%\\*\\*start of header")
+ (setq-local tex-end-of-header "%\\*\\*end of header")
+ (setq-local tex-trailer "\\bye\n"))
;;;###autoload
(define-derived-mode latex-mode tex-mode "LaTeX"
Entering Latex mode runs the hook `text-mode-hook', then
`tex-mode-hook', and finally `latex-mode-hook'. When the special
subshell is initiated, `tex-shell-hook' is run."
- (set (make-local-variable 'tex-command) latex-run-command)
- (set (make-local-variable 'tex-start-of-header)
- "\\\\document\\(style\\|class\\)")
- (set (make-local-variable 'tex-end-of-header) "\\\\begin\\s-*{document}")
- (set (make-local-variable 'tex-trailer) "\\end{document}\n")
+ (setq-local tex-command latex-run-command)
+ (setq-local tex-start-of-header "\\\\document\\(style\\|class\\)")
+ (setq-local tex-end-of-header "\\\\begin\\s-*{document}")
+ (setq-local tex-trailer "\\end{document}\n")
;; A line containing just $$ is treated as a paragraph separator.
;; A line starting with $$ starts a paragraph,
;; but does not separate paragraphs if it has more stuff on it.
"marginpar" "parbox" "caption"))
"\\|\\$\\$\\|[a-z]*\\(space\\|skip\\|page[a-z]*\\)"
"\\>\\)[ \t]*\\($\\|%\\)\\)"))
- (set (make-local-variable 'imenu-create-index-function)
- 'latex-imenu-create-index)
- (set (make-local-variable 'tex-face-alist) tex-latex-face-alist)
+ (setq-local imenu-create-index-function 'latex-imenu-create-index)
+ (setq-local tex-face-alist tex-latex-face-alist)
(add-hook 'fill-nobreak-predicate 'latex-fill-nobreak-predicate nil t)
- (set (make-local-variable 'indent-line-function) 'latex-indent)
- (set (make-local-variable 'fill-indent-according-to-mode) t)
+ (setq-local indent-line-function 'latex-indent)
+ (setq-local fill-indent-according-to-mode t)
(add-hook 'completion-at-point-functions
'latex-complete-data nil 'local)
- (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)
- (set (make-local-variable 'skeleton-end-hook) nil))
+ (setq-local outline-regexp latex-outline-regexp)
+ (setq-local outline-level 'latex-outline-level)
+ (setq-local forward-sexp-function 'latex-forward-sexp)
+ (setq-local skeleton-end-hook nil))
;;;###autoload
(define-derived-mode slitex-mode latex-mode "SliTeX"
(defun tex-common-initialization ()
;; Regexp isearch should accept newline and formfeed as whitespace.
- (set (make-local-variable 'search-whitespace-regexp) "[ \t\r\n\f]+")
+ (setq-local search-whitespace-regexp "[ \t\r\n\f]+")
;; A line containing just $$ is treated as a paragraph separator.
- (set (make-local-variable 'paragraph-start)
- "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$")
+ (setq-local paragraph-start "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$")
;; A line starting with $$ starts a paragraph,
;; but does not separate paragraphs if it has more stuff on it.
- (set (make-local-variable 'paragraph-separate)
- "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$[ \t]*$")
- (set (make-local-variable 'comment-start) "%")
- (set (make-local-variable 'comment-add) 1)
- (set (make-local-variable 'comment-start-skip)
- "\\(\\(^\\|[^\\\n]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)")
- (set (make-local-variable 'parse-sexp-ignore-comments) t)
- (set (make-local-variable 'compare-windows-whitespace)
- 'tex-categorize-whitespace)
- (set (make-local-variable 'facemenu-add-face-function)
- 'tex-facemenu-add-face-function)
- (set (make-local-variable 'facemenu-end-add-face) "}")
- (set (make-local-variable 'facemenu-remove-face-function) t)
- (set (make-local-variable 'font-lock-defaults)
- '((tex-font-lock-keywords tex-font-lock-keywords-1
- tex-font-lock-keywords-2 tex-font-lock-keywords-3)
- nil nil ((?$ . "\"")) nil
- ;; Who ever uses that anyway ???
- (font-lock-mark-block-function . mark-paragraph)
- (font-lock-syntactic-face-function
- . tex-font-lock-syntactic-face-function)
- (font-lock-unfontify-region-function
- . tex-font-lock-unfontify-region)))
- (set (make-local-variable 'syntax-propertize-function)
- (syntax-propertize-rules latex-syntax-propertize-rules))
+ (setq-local paragraph-separate "[ \t]*$\\|[\f\\\\%]\\|[ \t]*\\$\\$[ \t]*$")
+ (setq-local add-log-current-defun-function #'tex-current-defun-name)
+ (setq-local comment-start "%")
+ (setq-local comment-add 1)
+ (setq-local comment-start-skip
+ "\\(\\(^\\|[^\\\n]\\)\\(\\\\\\\\\\)*\\)\\(%+ *\\)")
+ (setq-local parse-sexp-ignore-comments t)
+ (setq-local compare-windows-whitespace 'tex-categorize-whitespace)
+ (setq-local facemenu-add-face-function 'tex-facemenu-add-face-function)
+ (setq-local facemenu-end-add-face "}")
+ (setq-local facemenu-remove-face-function t)
+ (setq-local font-lock-defaults
+ '((tex-font-lock-keywords tex-font-lock-keywords-1
+ tex-font-lock-keywords-2 tex-font-lock-keywords-3)
+ nil nil nil nil
+ ;; Who ever uses that anyway ???
+ (font-lock-mark-block-function . mark-paragraph)
+ (font-lock-syntactic-face-function
+ . tex-font-lock-syntactic-face-function)
+ (font-lock-unfontify-region-function
+ . tex-font-lock-unfontify-region)))
+ (setq-local syntax-propertize-function
+ (syntax-propertize-rules latex-syntax-propertize-rules))
;; TABs in verbatim environments don't do what you think.
- (set (make-local-variable 'indent-tabs-mode) nil)
+ (setq-local indent-tabs-mode nil)
;; Other vars that should be buffer-local.
(make-local-variable 'tex-command)
(make-local-variable 'tex-start-of-header)
(delete-char (length tex-open-quote))
t)))
(self-insert-command (prefix-numeric-value arg))
- (insert (if (memq (char-syntax (preceding-char)) '(?\( ?> ?\s))
+ (insert (if (or (memq (char-syntax (preceding-char)) '(?\( ?> ?\s))
+ (memq (preceding-char) '(?~)))
tex-open-quote tex-close-quote))))
(defun tex-validate-buffer ()
(defvar latex-complete-bibtex-cache nil)
-(defun latex-string-prefix-p (str1 str2)
- (eq t (compare-strings str1 nil nil str2 0 (length str1))))
+(define-obsolete-function-alias 'latex-string-prefix-p
+ 'string-prefix-p "24.3")
(defvar bibtex-reference-key)
(declare-function reftex-get-bibfile-list "reftex-cite.el" ())
keys)
(if (and (eq (car latex-complete-bibtex-cache)
(reftex-get-bibfile-list))
- (latex-string-prefix-p (nth 1 latex-complete-bibtex-cache)
+ (string-prefix-p (nth 1 latex-complete-bibtex-cache)
key))
;; Use the cache.
(setq keys (nth 2 latex-complete-bibtex-cache))
(looking-at bibtex-reference-key))
(push (match-string-no-properties 0) keys)))))
;; Fill the cache.
- (set (make-local-variable 'latex-complete-bibtex-cache)
- (list files key keys)))
+ (setq-local latex-complete-bibtex-cache (list files key keys)))
(complete-with-action action keys key pred)))))
(defun latex-complete-envnames ()
(save-excursion
(let ((pt (point)))
(skip-chars-backward "^ {}\n\t\\\\")
- (case (char-before)
- ((nil ?\s ?\n ?\t ?\}) nil)
+ (pcase (char-before)
+ ((or `nil ?\s ?\n ?\t ?\}) nil)
(?\\
;; TODO: Complete commands.
nil)
"Like `forward-sexp' but aware of multi-char elements and escaped parens."
(interactive "P")
(unless arg (setq arg 1))
- (let ((pos (point)))
+ (let ((pos (point))
+ (opoint 0))
(condition-case err
- (while (/= arg 0)
+ (while (and (/= (point) opoint)
+ (/= arg 0))
+ (setq opoint (point))
(setq arg
(if (> arg 0)
(progn (latex-forward-sexp-1) (1- arg))
(if (not (eq (char-syntax (preceding-char)) ?/))
(progn
;; Don't count single-char words.
- (unless (looking-at ".\\>") (incf count))
+ (unless (looking-at ".\\>") (cl-incf count))
(forward-char 1))
(let ((cmd
(buffer-substring-no-properties
;; The utility functions:
(define-derived-mode tex-shell shell-mode "TeX-Shell"
- (set (make-local-variable 'compilation-error-regexp-alist)
- tex-error-regexp-alist)
+ (setq-local compilation-error-regexp-alist tex-error-regexp-alist)
(compilation-shell-minor-mode t))
;;;###autoload
(let* ((dir (file-name-directory tex-last-temp-file))
(list (and (file-directory-p dir)
(file-name-all-completions
- (file-name-sans-extension
- (file-name-nondirectory tex-last-temp-file))
+ (file-name-base tex-last-temp-file)
dir))))
(while list
(if not-all
OUT describes the output file and is either a %-escaped string
or nil to indicate that there is no output file.")
-;; defsubst* gives better byte-code than defsubst.
-(defsubst* tex-string-prefix-p (str1 str2)
- "Return non-nil if STR1 is a prefix of STR2"
- (eq t (compare-strings str2 nil (length str1) str1 nil nil)))
+(define-obsolete-function-alias 'tex-string-prefix-p 'string-prefix-p "24.3")
(defun tex-guess-main-file (&optional all)
"Find a likely `tex-main-file'.
(with-current-buffer buf
(when (and (cond
((null all) (equal dir default-directory))
- ((eq all 'sub) (tex-string-prefix-p default-directory dir))
+ ((eq all 'sub) (string-prefix-p default-directory dir))
(t))
(stringp tex-main-file))
(throw 'found (expand-file-name tex-main-file)))))
(with-current-buffer buf
(when (and (cond
((null all) (equal dir default-directory))
- ((eq all 'sub) (tex-string-prefix-p default-directory dir))
+ ((eq all 'sub) (string-prefix-p default-directory dir))
(t))
buffer-file-name
;; (or (easy-mmode-derived-mode-p 'latex-mode)
(with-no-warnings
(when (boundp 'TeX-master)
(cond ((stringp TeX-master)
- (make-local-variable 'tex-main-file)
- (setq tex-main-file TeX-master))
+ (setq-local tex-main-file TeX-master))
((and (eq TeX-master t) buffer-file-name)
(file-relative-name buffer-file-name)))))
;; Try to guess the main file.
(if (null tex-shell)
(message "No TeX output buffer")
(setq window (display-buffer tex-shell))
- (save-selected-window
- (select-window window)
+ (with-selected-window window
(bury-buffer tex-shell)
(goto-char (point-max))
(recenter (if linenum
"Syntax table used while computing indentation.")
(defun latex-indent (&optional arg)
- (if (and (eq (get-text-property (line-beginning-position) 'face)
+ (if (and (eq (get-text-property (if (and (eobp) (bolp))
+ (max (point-min) (1- (point)))
+ (line-beginning-position)) 'face)
'tex-verbatim))
'noindent
(with-syntax-table tex-latex-indent-syntax-table
(cons (append (car font-lock-defaults) '(doctex-font-lock-keywords))
(mapcar
(lambda (x)
- (case (car-safe x)
- (font-lock-syntactic-face-function
+ (pcase (car-safe x)
+ (`font-lock-syntactic-face-function
(cons (car x) 'doctex-font-lock-syntactic-face-function))
- (t x)))
+ (_ x)))
(cdr font-lock-defaults))))
- (set (make-local-variable 'syntax-propertize-function)
- (syntax-propertize-rules doctex-syntax-propertize-rules)))
+ (setq-local syntax-propertize-function
+ (syntax-propertize-rules doctex-syntax-propertize-rules)))
(run-hooks 'tex-mode-load-hook)