887 lines
35 KiB
EmacsLisp
887 lines
35 KiB
EmacsLisp
|
;;; tex-info.el --- Support for editing Texinfo source. -*- lexical-binding: t; -*-
|
||
|
|
||
|
;; Copyright (C) 1993-2022 Free Software Foundation, Inc.
|
||
|
|
||
|
;; Maintainer: auctex-devel@gnu.org
|
||
|
;; Keywords: tex
|
||
|
|
||
|
;; This file is part of AUCTeX.
|
||
|
|
||
|
;; AUCTeX is free software; you can redistribute it and/or modify it
|
||
|
;; under the terms of the GNU General Public License as published by
|
||
|
;; the Free Software Foundation; either version 3, or (at your option)
|
||
|
;; any later version.
|
||
|
|
||
|
;; AUCTeX is distributed in the hope that it will be useful, but
|
||
|
;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
;; General Public License for more details.
|
||
|
|
||
|
;; You should have received a copy of the GNU General Public License
|
||
|
;; along with AUCTeX; see the file COPYING. If not, write to the Free
|
||
|
;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||
|
;; 02110-1301, USA.
|
||
|
|
||
|
;;; Code:
|
||
|
|
||
|
(eval-when-compile
|
||
|
(require 'cl-lib))
|
||
|
|
||
|
(require 'tex)
|
||
|
|
||
|
(require 'texinfo)
|
||
|
|
||
|
;;; Environments:
|
||
|
(defvar Texinfo-environment-list
|
||
|
'(("cartouche") ("command") ("copying") ("defcv") ("deffn") ("defivar")
|
||
|
("defmac") ("defmethod") ("defop") ("defopt") ("defspec")
|
||
|
("deftp") ("deftypefn") ("deftypefun") ("deftypevar") ("deftypevr")
|
||
|
("defun") ("defvar") ("defvr") ("description") ("detailmenu")
|
||
|
("direntry") ("display") ("documentdescription") ("enumerate")
|
||
|
("example") ("float") ("flushleft") ("flushright") ("format") ("ftable")
|
||
|
("group") ("html") ("ifclear") ("ifdocbook") ("ifhtml") ("ifinfo")
|
||
|
("ifnotdocbook") ("ifnothtml") ("ifnotinfo") ("ifnotplaintext")
|
||
|
("ifnottex") ("ifnotxml") ("ifplaintext") ("ifset") ("iftex")
|
||
|
("ifxml") ("ignore") ("itemize") ("lisp") ("macro") ("menu")
|
||
|
("multitable") ("quotation") ("smalldisplay") ("smallexample")
|
||
|
("smallformat") ("smalllisp") ("table") ("tex") ("titlepage")
|
||
|
("verbatim") ("vtable"))
|
||
|
"Alist of Texinfo environments.")
|
||
|
|
||
|
(defconst texinfo-environment-regexp
|
||
|
;; Overwrite version from `texinfo.el'.
|
||
|
(concat "^@\\("
|
||
|
(mapconcat #'car Texinfo-environment-list "\\|")
|
||
|
"\\|end\\)\\>")
|
||
|
"Regexp for environment-like Texinfo list commands.
|
||
|
Subexpression 1 is what goes into the corresponding `@end' statement.")
|
||
|
|
||
|
(defun Texinfo-environment (env &optional arg)
|
||
|
"Make Texinfo environment ENV.
|
||
|
With optional ARG, modify current environment."
|
||
|
;; XXX: This could be enhanced to act like `LaTeX-environment',
|
||
|
;; i.e. suggest a default environment and have its own history.
|
||
|
(interactive (list (completing-read "Environment: "
|
||
|
Texinfo-environment-list)
|
||
|
current-prefix-arg))
|
||
|
(if arg
|
||
|
(Texinfo-modify-environment env)
|
||
|
(Texinfo-insert-environment env)))
|
||
|
|
||
|
(defun Texinfo-insert-environment (env)
|
||
|
"Insert Texinfo environment ENV."
|
||
|
(if (and (TeX-active-mark)
|
||
|
(not (eq (mark) (point))))
|
||
|
(progn
|
||
|
(when (< (mark) (point))
|
||
|
(exchange-point-and-mark))
|
||
|
(unless (TeX-looking-at-backward "^[ \t]*")
|
||
|
(newline))
|
||
|
(insert "@" env)
|
||
|
(newline)
|
||
|
(goto-char (mark))
|
||
|
(unless (TeX-looking-at-backward "^[ \t]*")
|
||
|
(newline))
|
||
|
(insert "@end " env)
|
||
|
(save-excursion (newline))
|
||
|
(end-of-line 0))
|
||
|
(insert "@" env "\n\n@end " env "\n")
|
||
|
(if (null (cdr-safe (assoc "defcv" Texinfo-environment-list)))
|
||
|
(forward-line -2))))
|
||
|
|
||
|
(defun Texinfo-modify-environment (env)
|
||
|
"Change current environment to environment ENV."
|
||
|
(save-excursion
|
||
|
(Texinfo-find-env-end)
|
||
|
(re-search-backward (concat (regexp-quote TeX-esc) "end \\([a-zA-Z]*\\)")
|
||
|
(line-beginning-position))
|
||
|
(replace-match env t t nil 1)
|
||
|
(beginning-of-line)
|
||
|
(Texinfo-find-env-start)
|
||
|
(re-search-forward (concat (regexp-quote TeX-esc) "\\([a-zA-Z]*\\)")
|
||
|
(line-end-position))
|
||
|
(replace-match env t t nil 1)))
|
||
|
|
||
|
(defun Texinfo-find-env-end ()
|
||
|
"Move point to the end of the current environment."
|
||
|
(interactive)
|
||
|
(let* ((envs (mapcar #'car Texinfo-environment-list))
|
||
|
(regexp (concat "^[ \t]*" (regexp-quote TeX-esc) "\\(end \\)*"
|
||
|
(regexp-opt envs t) "\\b"))
|
||
|
(orig-pos (point))
|
||
|
(level 1)
|
||
|
case-fold-search)
|
||
|
(save-restriction
|
||
|
(save-excursion
|
||
|
(save-excursion
|
||
|
(beginning-of-line)
|
||
|
;; Stop if point is inside of an @end <env> command, but not
|
||
|
;; if it is behind it.
|
||
|
(when (and (looking-at regexp)
|
||
|
(match-string 1)
|
||
|
(> (match-end 0) orig-pos))
|
||
|
(setq level 0)))
|
||
|
(while (and (> level 0) (re-search-forward regexp nil t))
|
||
|
(if (match-string 1)
|
||
|
(setq level (1- level))
|
||
|
(setq level (1+ level)))))
|
||
|
(if (= level 0)
|
||
|
(goto-char (match-end 0))
|
||
|
(error "Can't locate end of current environment")))))
|
||
|
|
||
|
(defun Texinfo-find-env-start ()
|
||
|
"Move point to the start of the current environment."
|
||
|
(interactive)
|
||
|
(let* ((envs (mapcar #'car Texinfo-environment-list))
|
||
|
(regexp (concat "^[ \t]*\\(" (regexp-quote TeX-esc) "\\)\\(end \\)*"
|
||
|
(regexp-opt envs t) "\\b"))
|
||
|
(level 1)
|
||
|
(orig-pos (point))
|
||
|
case-fold-search)
|
||
|
(save-restriction
|
||
|
(save-excursion
|
||
|
(save-excursion
|
||
|
(beginning-of-line)
|
||
|
;; Stop if point is inside of an @<env> command, but not if
|
||
|
;; it is before it.
|
||
|
(when (and (looking-at regexp)
|
||
|
(not (match-string 2))
|
||
|
(< (match-beginning 1) orig-pos))
|
||
|
(setq level 0)))
|
||
|
(while (and (> level 0) (re-search-backward regexp nil t))
|
||
|
(if (match-string 2)
|
||
|
(setq level (1+ level))
|
||
|
(setq level (1- level)))))
|
||
|
(if (= level 0)
|
||
|
(goto-char (match-beginning 0))
|
||
|
(error "Can't locate start of current environment")))))
|
||
|
|
||
|
(defun Texinfo-mark-environment (&optional count)
|
||
|
"Set mark to end of current environment and point to the matching begin.
|
||
|
If prefix argument COUNT is given, mark the respective number of
|
||
|
enclosing environments. The command will not work properly if
|
||
|
there are unbalanced begin-end pairs in comments and verbatim
|
||
|
environments."
|
||
|
;; TODO:
|
||
|
;; This is identical to the LaTeX counterpart but for the find begin/end
|
||
|
;; functions. So some day the implemenation should be factorized.
|
||
|
(interactive "p")
|
||
|
(setq count (if count (abs count) 1))
|
||
|
(let ((cur (point)) beg end)
|
||
|
;; Only change point and mark after beginning and end were found.
|
||
|
;; Point should not end up in the middle of nowhere if the search fails.
|
||
|
(save-excursion
|
||
|
(dotimes (_ count)
|
||
|
(Texinfo-find-env-end))
|
||
|
(setq end (line-beginning-position 2))
|
||
|
(goto-char cur)
|
||
|
(dotimes (c count)
|
||
|
(Texinfo-find-env-start)
|
||
|
(unless (= (1+ c) count)
|
||
|
(beginning-of-line 0)))
|
||
|
(setq beg (point)))
|
||
|
(push-mark end)
|
||
|
(goto-char beg)
|
||
|
(TeX-activate-region)))
|
||
|
|
||
|
(defun Texinfo-mark-section (&optional no-subsection)
|
||
|
"Mark current section, with inclusion of any containing node.
|
||
|
|
||
|
The current section is detected as starting by any of the
|
||
|
structuring commands matched by regexp in variable
|
||
|
`outline-regexp' which in turn is a regexp matching any element
|
||
|
of variable `texinfo-section-list'.
|
||
|
|
||
|
If optional argument NO-SUBSECTION is set to any integer or is a
|
||
|
non nil empty argument (that is, `\\[universal-argument] \\[Texinfo-mark-section]'),
|
||
|
then mark the current section with exclusion of any subsections.
|
||
|
|
||
|
Otherwise, any included subsections are also marked along with
|
||
|
current section.
|
||
|
|
||
|
Note that when current section is starting immediatley after a
|
||
|
node commande, then the node command is also marked as part as
|
||
|
the section."
|
||
|
(interactive "P")
|
||
|
(let (beg end is-beg-section is-end-section
|
||
|
(section-re (concat "^\\s-*" outline-regexp)))
|
||
|
(if (and (consp no-subsection) (eq (car no-subsection) 4))
|
||
|
;; section with exclusion of any subsection
|
||
|
(setq beg (save-excursion
|
||
|
(unless (looking-at section-re)
|
||
|
(end-of-line))
|
||
|
(re-search-backward section-re nil t))
|
||
|
is-beg-section t
|
||
|
end (save-excursion
|
||
|
(beginning-of-line)
|
||
|
(when
|
||
|
(re-search-forward (concat section-re
|
||
|
"\\|^\\s-*@bye\\_>" )
|
||
|
nil t)
|
||
|
(save-match-data
|
||
|
(beginning-of-line)
|
||
|
(point))))
|
||
|
is-end-section (match-string 1))
|
||
|
;; full section without exclusion of any subsection
|
||
|
(let (section-command-level)
|
||
|
(setq beg
|
||
|
(save-excursion
|
||
|
(end-of-line)
|
||
|
(re-search-backward section-re nil t)))
|
||
|
(when beg
|
||
|
(setq is-beg-section t
|
||
|
section-command-level
|
||
|
(cadr (assoc (match-string 1) texinfo-section-list))
|
||
|
end
|
||
|
(save-excursion
|
||
|
(beginning-of-line)
|
||
|
(while
|
||
|
(and (re-search-forward
|
||
|
(concat section-re "\\|^\\s-*@bye\\_>" ) nil t)
|
||
|
(or (null (setq is-end-section (match-string 1)))
|
||
|
(> (cadr (assoc is-end-section
|
||
|
texinfo-section-list))
|
||
|
section-command-level))))
|
||
|
(when (match-string 0)
|
||
|
(beginning-of-line)
|
||
|
(point))))))); (if ...)
|
||
|
(when (and beg end)
|
||
|
;; now take also enclosing node of beg and end
|
||
|
(let ((before-@node
|
||
|
(lambda (pos)
|
||
|
(save-excursion
|
||
|
(goto-char pos)
|
||
|
(while (and
|
||
|
(null (bobp))
|
||
|
(progn
|
||
|
(beginning-of-line 0)
|
||
|
(looking-at
|
||
|
"^\\s-*\\($\\|@\\(c\\|comment\\)\\_>\\)"))))
|
||
|
(when (looking-at "^\\s-*@node\\_>")
|
||
|
(point))))))
|
||
|
(when is-beg-section
|
||
|
(setq beg (or (funcall before-@node beg) beg)))
|
||
|
(when is-end-section
|
||
|
(setq end (or (funcall before-@node end) end))))
|
||
|
|
||
|
(push-mark end)
|
||
|
(goto-char beg)
|
||
|
(TeX-activate-region) )))
|
||
|
|
||
|
(defun Texinfo-mark-node ()
|
||
|
"Mark the current node.
|
||
|
This is the node in which the pointer is. It is starting at
|
||
|
previous beginning of keyword `@node' and ending at next
|
||
|
beginning of keyword `@node' or `@bye'."
|
||
|
(interactive)
|
||
|
(let ((beg (save-excursion
|
||
|
(unless (looking-at "^\\s-*@\\(?:node\\)\\_>")
|
||
|
(end-of-line))
|
||
|
(re-search-backward "^\\s-*@\\(?:node\\)\\_>" nil t )))
|
||
|
(end (save-excursion
|
||
|
(beginning-of-line)
|
||
|
(and (re-search-forward "^\\s-*@\\(?:node\\|bye\\)\\_>" nil t )
|
||
|
(progn (beginning-of-line) (point))))))
|
||
|
|
||
|
(when (and beg end)
|
||
|
(push-mark end)
|
||
|
(goto-char beg)
|
||
|
(TeX-activate-region) )))
|
||
|
|
||
|
(defun Texinfo-nodename-de-escape (node-name)
|
||
|
"In NODE-NAME, convert `@comma{}' commands to the corresponding `,'
|
||
|
character. Return the resulting string."
|
||
|
(let ((pos 0) (map '(("comma" . ","))))
|
||
|
(while (and (< pos (length
|
||
|
node-name))
|
||
|
(string-match "@\\(comma\\)[[:blank:]]*{}" node-name pos))
|
||
|
(setq node-name (concat (substring node-name 0 (match-beginning 0))
|
||
|
(cdr (assoc-string (match-string 1 node-name) map))
|
||
|
(substring node-name (match-end 0)))
|
||
|
pos (1+ (match-beginning 0)))))
|
||
|
node-name)
|
||
|
|
||
|
|
||
|
(defun Texinfo-nodename-escape (node-name)
|
||
|
"Convert in NODE-NAME the `,' characters to `@comma{}'
|
||
|
commands. Return the resulting string."
|
||
|
(let* ((pos 0)
|
||
|
(map '(("," . "comma")))
|
||
|
(re (regexp-opt (mapcar #'car map))) )
|
||
|
(while (and (< pos (length node-name)) (string-match re node-name pos))
|
||
|
(setq node-name (concat (substring node-name 0 (match-beginning 0))
|
||
|
"@" (cdr (assoc-string (match-string 0 node-name) map))
|
||
|
"{}"
|
||
|
(substring node-name (match-end 0)))
|
||
|
pos (1+ (match-beginning 0)))))
|
||
|
node-name)
|
||
|
|
||
|
|
||
|
(defun Texinfo-make-node-list ()
|
||
|
;; Build list of nodes in current buffer.
|
||
|
;; (What about using `imenu--index-alist'?)
|
||
|
;; FIXME: Support multi-file documents.
|
||
|
(save-excursion
|
||
|
(goto-char (point-min))
|
||
|
(let (nodes dups)
|
||
|
(while (re-search-forward "^@node\\b" nil t)
|
||
|
(skip-chars-forward "[:blank:]")
|
||
|
(cl-pushnew (list (Texinfo-nodename-de-escape
|
||
|
(buffer-substring-no-properties
|
||
|
(point) (progn (skip-chars-forward "^\r\n,")
|
||
|
(skip-chars-backward "[:blank:]")
|
||
|
(point)))))
|
||
|
nodes
|
||
|
:test (lambda (a b)
|
||
|
(when (equal a b)
|
||
|
(push (cons a (line-number-at-pos (point))) dups)
|
||
|
t))))
|
||
|
(when dups
|
||
|
(display-warning
|
||
|
'AUCTeX
|
||
|
(format "There are duplicate nodes:\n%s"
|
||
|
(mapconcat (lambda (dup)
|
||
|
(format " %s on line %d" (car dup) (cdr dup)))
|
||
|
(nreverse dups)
|
||
|
"\n"))))
|
||
|
(nreverse nodes))))
|
||
|
|
||
|
(defun Texinfo-insert-node ()
|
||
|
"Insert a Texinfo node in the current buffer.
|
||
|
That means, insert the string `@node' and prompt for current,
|
||
|
next, previous and upper node. If there is an active region, use
|
||
|
this for the current node and inhibit the prompt for it. Insert
|
||
|
a comment on the following line indicating the order of arguments
|
||
|
for @node."
|
||
|
(interactive)
|
||
|
(let ((active-mark (and (TeX-active-mark) (not (eq (mark) (point)))))
|
||
|
(nodes (Texinfo-make-node-list))
|
||
|
node-name next-node previous-node up-node)
|
||
|
(unless active-mark
|
||
|
(setq node-name (Texinfo-nodename-escape
|
||
|
(TeX-read-string "Node name: "))))
|
||
|
;; FIXME: What if key binding for `minibuffer-complete' was changed?
|
||
|
;; `substitute-command-keys' doesn't return the correct value.
|
||
|
(setq next-node (Texinfo-nodename-escape
|
||
|
(completing-read "Next node (TAB completes): " nodes)))
|
||
|
(setq previous-node
|
||
|
(Texinfo-nodename-escape
|
||
|
(completing-read "Previous node (TAB completes): " nodes)))
|
||
|
(setq up-node (Texinfo-nodename-escape
|
||
|
(completing-read "Upper node (TAB completes): " nodes)))
|
||
|
(when (and active-mark
|
||
|
(< (mark) (point)))
|
||
|
(exchange-point-and-mark))
|
||
|
(insert "@node ")
|
||
|
(if active-mark
|
||
|
(goto-char (mark))
|
||
|
(insert node-name))
|
||
|
(insert ", " next-node ", " previous-node ", " up-node
|
||
|
"\n@comment node-name, next, previous, up\n")
|
||
|
;; Position point at first empty field.
|
||
|
(unless (and (or (> (length node-name) 0) active-mark)
|
||
|
(> (length next-node) 0)
|
||
|
(> (length previous-node) 0)
|
||
|
(> (length up-node) 0))
|
||
|
(forward-line -2)
|
||
|
(forward-char 6)
|
||
|
(catch 'break
|
||
|
(if (or (> (length node-name) 0) active-mark)
|
||
|
(progn (skip-chars-forward "^,") (forward-char 2))
|
||
|
(throw 'break nil))
|
||
|
(dolist (node (list next-node previous-node up-node))
|
||
|
(if (> (length node) 0)
|
||
|
(progn (skip-chars-forward "^,") (forward-char 2))
|
||
|
(throw 'break nil)))))))
|
||
|
|
||
|
(defun Texinfo-arg-nodename (optional &optional prompt _definition)
|
||
|
"Prompt for a node name completing with known node names.
|
||
|
OPTIONAL is ignored.
|
||
|
Use PROMPT as the prompt string.
|
||
|
If DEFINITION is non-nil, then chosen node name is a node name to be
|
||
|
added to the list of defined node names. Current implementation
|
||
|
ignored DEFINITION as the full document is scanned for node names at
|
||
|
each invocation."
|
||
|
(let ((node-name (completing-read (TeX-argument-prompt optional prompt "Node")
|
||
|
(Texinfo-make-node-list))))
|
||
|
(insert "{" (Texinfo-nodename-escape node-name) "}" )))
|
||
|
|
||
|
(defun Texinfo-arg-lrc (_optional &rest _args)
|
||
|
(let ((l (read-from-minibuffer "Enter left part: "))
|
||
|
(c (read-from-minibuffer "Enter center part: "))
|
||
|
(r (read-from-minibuffer "Enter right part: ")))
|
||
|
(insert " " l " @| " c " @| " r)))
|
||
|
|
||
|
(defun Texinfo-arg-next-line (_optional &rest _args)
|
||
|
"Go to the beginning of next line if we are at the end of line.
|
||
|
Otherwise insert an end-of-line."
|
||
|
(if (eolp) (forward-line) (insert "\n")))
|
||
|
|
||
|
(defun Texinfo-arg-on|off (optional &optional prompt style)
|
||
|
"Prompt for a boolean input.
|
||
|
OPTIONAL is ignored.
|
||
|
Use PROMPT as the prompt string.
|
||
|
STYLE may be one of `:on|off' or `:true|false', if omitted `:on|off'
|
||
|
is assumed by default."
|
||
|
(let ((collection (cdr (assq style
|
||
|
'((nil . #1=("on" "off"))
|
||
|
(:on|off . #1#)
|
||
|
(:true|false "true" "false"))))))
|
||
|
(insert (if (y-or-n-p (TeX-argument-prompt optional prompt (concat (car collection) ", not " (cadr collection))))
|
||
|
(car collection)
|
||
|
(cadr collection)))))
|
||
|
|
||
|
(defun Texinfo-arg-choice (optional &optional prompt collection)
|
||
|
(insert (completing-read (TeX-argument-prompt optional prompt "Key")
|
||
|
collection)))
|
||
|
|
||
|
;; Silence the byte-compiler from warnings for variables and functions declared
|
||
|
;; in reftex.
|
||
|
(defvar reftex-section-levels-all)
|
||
|
(defvar reftex-level-indent)
|
||
|
(defvar reftex-label-menu-flags)
|
||
|
(defvar reftex-tables-dirty)
|
||
|
(defvar reftex-label-alist-builtin)
|
||
|
|
||
|
(declare-function reftex-match-string "reftex" (n))
|
||
|
(declare-function reftex-section-number "reftex-parse" (&optional level star))
|
||
|
(declare-function reftex-nicify-text "reftex" (text))
|
||
|
(declare-function reftex-ensure-compiled-variables "reftex" ())
|
||
|
|
||
|
(defun Texinfo-reftex-section-info (file)
|
||
|
;; Return a section entry for the current match.
|
||
|
;; Carefull: This function expects the match-data to be still in place!
|
||
|
(let* ((marker (set-marker (make-marker) (1- (match-beginning 3))))
|
||
|
(macro (reftex-match-string 3))
|
||
|
(level-exp (cdr (assoc macro reftex-section-levels-all)))
|
||
|
(level (if (symbolp level-exp)
|
||
|
(save-match-data (funcall level-exp))
|
||
|
level-exp))
|
||
|
(unnumbered (< level 0))
|
||
|
(level (abs level))
|
||
|
(section-number (reftex-section-number level unnumbered))
|
||
|
(text1 (save-match-data
|
||
|
(save-excursion
|
||
|
(buffer-substring-no-properties (point) (progn (end-of-line) (point))))))
|
||
|
(literal (buffer-substring-no-properties
|
||
|
(1- (match-beginning 3))
|
||
|
(min (point-max) (+ (match-end 0) (length text1) 1))))
|
||
|
;; Literal can be too short since text1 too short. No big problem.
|
||
|
(text (reftex-nicify-text text1)))
|
||
|
|
||
|
;; Add section number and indentation
|
||
|
(setq text
|
||
|
(concat
|
||
|
(make-string (* reftex-level-indent level) ?\ )
|
||
|
(if (nth 1 reftex-label-menu-flags) ; section number flag
|
||
|
(concat section-number " "))
|
||
|
text))
|
||
|
(prog1
|
||
|
(list 'toc "toc" text file marker level section-number
|
||
|
literal (marker-position marker))
|
||
|
(set-marker marker nil))))
|
||
|
|
||
|
(defun Texinfo-reftex-hook ()
|
||
|
"Hook function to plug Texinfo into RefTeX."
|
||
|
;; force recompilation of variables
|
||
|
(when (string= TeX-base-mode-name "Texinfo")
|
||
|
;; dirty temporary hook to remove when reftex has a Texinfo builtin
|
||
|
;; TODO --- taken on <2014-01-06 mon> --- remove the dirty trick once reftex
|
||
|
;; has been corrected for long enough a time
|
||
|
(unless (assq 'Texinfo reftex-label-alist-builtin)
|
||
|
(setq reftex-label-alist-builtin (append reftex-label-alist-builtin
|
||
|
'((Texinfo "Texinfo default environments" nil)))))
|
||
|
(dolist (v `((reftex-section-pre-regexp . "@")
|
||
|
; section post-regexp must contain exactly one group
|
||
|
(reftex-section-post-regexp . "\\([ \t]+\\)")
|
||
|
(reftex-section-info-function . Texinfo-reftex-section-info)
|
||
|
(reftex-default-label-alist-entries . (Texinfo))
|
||
|
(reftex-section-levels
|
||
|
. ,(mapcar
|
||
|
(lambda (x)
|
||
|
(if (string-match "\\(\\`unnumbered\\)\\|\\(heading\\'\\)\\|\\(\\`top\\'\\)"
|
||
|
(car x))
|
||
|
(cons (car x) (- (cadr x)))
|
||
|
(cons (car x) (cadr x))))
|
||
|
texinfo-section-list))))
|
||
|
(set (make-local-variable (car v) ) (cdr v)))
|
||
|
(reftex-ensure-compiled-variables)))
|
||
|
|
||
|
;;; Keymap:
|
||
|
|
||
|
(defvar Texinfo-mode-map
|
||
|
(let ((map (make-sparse-keymap)))
|
||
|
(set-keymap-parent map TeX-mode-map)
|
||
|
|
||
|
;; From texinfo.el
|
||
|
;; bindings for updating nodes and menus
|
||
|
(define-key map "\C-c\C-um" #'texinfo-master-menu)
|
||
|
(define-key map "\C-c\C-u\C-m" #'texinfo-make-menu)
|
||
|
(define-key map "\C-c\C-u\C-n" #'texinfo-update-node)
|
||
|
(define-key map "\C-c\C-u\C-e" #'texinfo-every-node-update)
|
||
|
(define-key map "\C-c\C-u\C-a" #'texinfo-all-menus-update)
|
||
|
|
||
|
;; Simulating LaTeX-mode
|
||
|
(define-key map "\C-c\C-e" #'Texinfo-environment)
|
||
|
(define-key map "\C-c." #'Texinfo-mark-environment)
|
||
|
(define-key map "\C-c*" #'Texinfo-mark-section)
|
||
|
(define-key map "\M-\C-h" #'Texinfo-mark-node)
|
||
|
(define-key map "\C-c\n" #'texinfo-insert-@item)
|
||
|
(or (key-binding "\e\r")
|
||
|
(define-key map "\e\r" #'texinfo-insert-@item)) ;*** Alias
|
||
|
(define-key map "\C-c\C-s" #'Texinfo-insert-node)
|
||
|
(define-key map "\C-c]" #'texinfo-insert-@end)
|
||
|
|
||
|
;; Override some bindings in `TeX-mode-map'
|
||
|
;; FIXME: Inside @math{}, you can use all plain TeX math commands
|
||
|
;; even in Texinfo documents. Thus it might be nice to develop
|
||
|
;; context sensitive command so that the following four keys
|
||
|
;; inherit the command in `TeX-mode-map' inside @math{}.
|
||
|
(define-key map "$" #'self-insert-command)
|
||
|
(define-key map "^" #'self-insert-command)
|
||
|
(define-key map "_" #'self-insert-command)
|
||
|
(define-key map "\\" #'self-insert-command)
|
||
|
;; Users benefit from `TeX-electric-macro' even in Texinfo mode
|
||
|
(define-key map "@" #'TeX-insert-backslash)
|
||
|
map)
|
||
|
"Keymap for Texinfo mode.")
|
||
|
|
||
|
(easy-menu-define Texinfo-command-menu
|
||
|
Texinfo-mode-map
|
||
|
"Menu used in Texinfo mode for external commands."
|
||
|
(TeX-mode-specific-command-menu 'texinfo-mode))
|
||
|
|
||
|
(easy-menu-define Texinfo-mode-menu
|
||
|
Texinfo-mode-map
|
||
|
"Menu used in Texinfo mode."
|
||
|
`("Texinfo"
|
||
|
["Node ..." texinfo-insert-@node
|
||
|
:help "Insert a node"]
|
||
|
["Macro ..." TeX-insert-macro
|
||
|
:help "Insert a macro and possibly arguments"]
|
||
|
["Complete Macro" TeX-complete-symbol
|
||
|
:help "Complete the current macro"]
|
||
|
["Environment ..." Texinfo-insert-environment
|
||
|
:help "Insert an environment"]
|
||
|
["Item" texinfo-insert-@item
|
||
|
:help "Insert an @item"]
|
||
|
"-"
|
||
|
("Insert Font"
|
||
|
["Emphasize" (TeX-font nil ?\C-e) :keys "C-c C-f C-e"]
|
||
|
["Bold" (TeX-font nil ?\C-b) :keys "C-c C-f C-b"]
|
||
|
["Typewriter" (TeX-font nil ?\C-t) :keys "C-c C-f C-t"]
|
||
|
["Small Caps" (TeX-font nil ?\C-c) :keys "C-c C-f C-c"]
|
||
|
["Italic" (TeX-font nil ?\C-i) :keys "C-c C-f C-i"]
|
||
|
["Sample" (TeX-font nil ?\C-s) :keys "C-c C-f C-s"]
|
||
|
["Roman" (TeX-font nil ?\C-r) :keys "C-c C-f C-r"])
|
||
|
("Replace Font"
|
||
|
["Emphasize" (TeX-font t ?\C-e) :keys "C-u C-c C-f C-e"]
|
||
|
["Bold" (TeX-font t ?\C-b) :keys "C-u C-c C-f C-b"]
|
||
|
["Typewriter" (TeX-font t ?\C-t) :keys "C-u C-c C-f C-t"]
|
||
|
["Small Caps" (TeX-font t ?\C-c) :keys "C-u C-c C-f C-c"]
|
||
|
["Italic" (TeX-font t ?\C-i) :keys "C-u C-c C-f C-i"]
|
||
|
["Sample" (TeX-font t ?\C-s) :keys "C-u C-c C-f C-s"]
|
||
|
["Roman" (TeX-font t ?\C-r) :keys "C-u C-c C-f C-r"])
|
||
|
["Delete Font" (TeX-font t ?\C-d) :keys "C-c C-f C-d"]
|
||
|
"-"
|
||
|
["Create Master Menu" texinfo-master-menu
|
||
|
:help "Make a master menu for the whole Texinfo file"]
|
||
|
["Create Menu" texinfo-make-menu
|
||
|
:help "Make or update the menu for the current section"]
|
||
|
["Update Node" texinfo-update-node
|
||
|
:help "Update the current node"]
|
||
|
["Update Every Node" texinfo-every-node-update
|
||
|
:help "Update every node in the current file"]
|
||
|
["Update All Menus" texinfo-all-menus-update
|
||
|
:help "Update every menu in the current file"]
|
||
|
"-"
|
||
|
("Commenting"
|
||
|
["Comment or Uncomment Region"
|
||
|
comment-or-uncomment-region
|
||
|
:help "Comment or uncomment the currently selected region"]
|
||
|
["Comment or Uncomment Paragraph"
|
||
|
TeX-comment-or-uncomment-paragraph
|
||
|
:help "Comment or uncomment the current paragraph"])
|
||
|
,TeX-fold-menu
|
||
|
"-"
|
||
|
. ,TeX-common-menu-entries))
|
||
|
|
||
|
(defvar Texinfo-font-list
|
||
|
'((?\C-b "@b{" "}")
|
||
|
(?\C-c "@sc{" "}")
|
||
|
(?\C-e "@emph{" "}")
|
||
|
(?\C-i "@i{" "}")
|
||
|
(?\C-r "@r{" "}")
|
||
|
(?\C-s "@samp{" "}")
|
||
|
(?\C-t "@t{" "}")
|
||
|
(?s "@strong{" "}")
|
||
|
(?\C-f "@file{" "}")
|
||
|
(?d "@dfn{" "}")
|
||
|
(?\C-v "@var{" "}")
|
||
|
(?k "@key{" "}")
|
||
|
(?\C-k "@kbd{" "}")
|
||
|
(?c "@code{" "}")
|
||
|
(?C "@cite{" "}")
|
||
|
(?\C-d "" "" t))
|
||
|
"Font commands used in Texinfo mode. See `TeX-font-list'.")
|
||
|
|
||
|
;;; Mode:
|
||
|
|
||
|
;;;###autoload
|
||
|
(defalias 'Texinfo-mode #'texinfo-mode)
|
||
|
|
||
|
;;;###autoload
|
||
|
(defun TeX-texinfo-mode ()
|
||
|
"Major mode in AUCTeX for editing Texinfo files.
|
||
|
|
||
|
Special commands:
|
||
|
\\{Texinfo-mode-map}
|
||
|
|
||
|
Entering Texinfo mode calls the value of `text-mode-hook' and then the
|
||
|
value of `Texinfo-mode-hook'."
|
||
|
(interactive)
|
||
|
(kill-all-local-variables)
|
||
|
(setq TeX-mode-p t)
|
||
|
(setq TeX-output-extension (if TeX-PDF-mode "pdf" "dvi"))
|
||
|
(setq TeX-sentinel-default-function #'TeX-TeX-sentinel)
|
||
|
;; Mostly stolen from texinfo.el
|
||
|
(setq TeX-base-mode-name "Texinfo")
|
||
|
(setq major-mode 'texinfo-mode)
|
||
|
(use-local-map Texinfo-mode-map)
|
||
|
(set-syntax-table texinfo-mode-syntax-table)
|
||
|
|
||
|
(set (make-local-variable 'page-delimiter)
|
||
|
(concat
|
||
|
"^@node [ \t]*[Tt]op\\|^@\\("
|
||
|
texinfo-chapter-level-regexp
|
||
|
"\\)"))
|
||
|
(set (make-local-variable 'require-final-newline) t)
|
||
|
(set (make-local-variable 'indent-tabs-mode) nil)
|
||
|
(set (make-local-variable 'paragraph-separate)
|
||
|
(concat "@[a-zA-Z]*[ \n]\\|" paragraph-separate))
|
||
|
(set (make-local-variable 'paragraph-start)
|
||
|
(concat "@[a-zA-Z]*[ \n]\\|" paragraph-start))
|
||
|
(set (make-local-variable 'fill-column) 72)
|
||
|
(set (make-local-variable 'comment-start) "@c ")
|
||
|
(set (make-local-variable 'comment-start-skip) "@c +\\|@comment +")
|
||
|
(set (make-local-variable 'comment-use-syntax) nil)
|
||
|
(setq TeX-comment-start-regexp "@c\\(?:omment\\)?\\>")
|
||
|
(set (make-local-variable 'words-include-escapes) t)
|
||
|
(set (make-local-variable 'imenu-generic-expression)
|
||
|
texinfo-imenu-generic-expression)
|
||
|
|
||
|
(set (make-local-variable 'font-lock-defaults)
|
||
|
'(texinfo-font-lock-keywords nil nil nil backward-paragraph))
|
||
|
(set (make-local-variable 'syntax-propertize-function)
|
||
|
texinfo-syntax-propertize-function)
|
||
|
|
||
|
;; Outline settings.
|
||
|
(set (make-local-variable 'outline-regexp)
|
||
|
(concat "@\\("
|
||
|
(mapconcat #'car texinfo-section-list "\\>\\|")
|
||
|
"\\>\\)"))
|
||
|
|
||
|
;; Mostly AUCTeX stuff
|
||
|
(set (make-local-variable 'TeX-command-current) #'TeX-command-master)
|
||
|
|
||
|
(setq TeX-default-extension "texi")
|
||
|
(set (make-local-variable 'TeX-esc) "@")
|
||
|
|
||
|
(set (make-local-variable 'TeX-auto-regexp-list) 'TeX-auto-empty-regexp-list)
|
||
|
|
||
|
(setq TeX-command-default "TeX")
|
||
|
(setq TeX-header-end "%*end")
|
||
|
(setq TeX-trailer-start (regexp-quote (concat TeX-esc "bye")))
|
||
|
|
||
|
(set (make-local-variable 'TeX-complete-list)
|
||
|
(list (list "@\\([a-zA-Z]*\\)" 1 'TeX-symbol-list-filtered nil)
|
||
|
(list "" TeX-complete-word)))
|
||
|
|
||
|
(set (make-local-variable 'TeX-font-list) Texinfo-font-list)
|
||
|
(set (make-local-variable 'TeX-font-replace-function)
|
||
|
#'TeX-font-replace-macro)
|
||
|
(set (make-local-variable 'TeX-style-hook-dialect) :texinfo)
|
||
|
|
||
|
(add-hook 'find-file-hook (lambda ()
|
||
|
(unless (file-exists-p (buffer-file-name))
|
||
|
(TeX-master-file nil nil t)))
|
||
|
nil t)
|
||
|
|
||
|
(when (and (boundp 'add-log-current-defun-function)
|
||
|
(fboundp 'texinfo-current-defun-name))
|
||
|
(set (make-local-variable 'add-log-current-defun-function)
|
||
|
#'texinfo-current-defun-name))
|
||
|
|
||
|
(TeX-add-symbols
|
||
|
'("acronym" "Acronym")
|
||
|
'("allowcodebreaks" (TeX-arg-literal " ") (Texinfo-arg-on|off nil :true|false) (Texinfo-arg-next-line))
|
||
|
'("appendix" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("appendixsec" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("appendixsection" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("appendixsubsec" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("appendixsubsubsec" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("asis")
|
||
|
'("atchar" nil)
|
||
|
'("author" (TeX-arg-literal " ") (TeX-arg-free "Author"))
|
||
|
'("b" "Text")
|
||
|
'("bullet")
|
||
|
'("bye")
|
||
|
'("c" (TeX-arg-literal " ") (TeX-arg-free "Comment"))
|
||
|
'("caption" "Caption"
|
||
|
;; TODO: caption is meaningful only inside float env. Maybe some checking
|
||
|
;; and warning would be good.
|
||
|
)
|
||
|
'("center" (TeX-arg-literal " ") (TeX-arg-free "Line of text"))
|
||
|
'("chapheading" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("chapter" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("cindex" (TeX-arg-literal " ") (TeX-arg-free "Entry"))
|
||
|
'("cite" "Reference")
|
||
|
'("clear" (TeX-arg-literal " ") (TeX-arg-free "Flag"))
|
||
|
'("code" "Sample code")
|
||
|
'("codequotebacktick" (TeX-arg-literal " ") (Texinfo-arg-on|off) (Texinfo-arg-next-line))
|
||
|
'("codequoteundirected" (TeX-arg-literal " ") (Texinfo-arg-on|off) (Texinfo-arg-next-line))
|
||
|
'("command" "Command")
|
||
|
'("comment" (TeX-arg-literal " ") (TeX-arg-free "Comment"))
|
||
|
'("contents")
|
||
|
'("copyright" nil)
|
||
|
'("defcodeindex" (TeX-arg-literal " ") (TeX-arg-free "Index name"))
|
||
|
'("defindex" (TeX-arg-literal " ") (TeX-arg-free "Index name"))
|
||
|
'("dfn" "Term")
|
||
|
'("dmn" "Dimension")
|
||
|
'("documentlanguage" (TeX-arg-literal " ") (Texinfo-arg-choice "Language" ("ca" "cs" "de" "en" "es" "fr" "hu" "is" "it" "ja" "nb" "nl" "nn" "pl" "pt" "ru" "sr" "tr" "uk")) (Texinfo-arg-next-line))
|
||
|
'("documentencoding" (TeX-arg-literal " ") (Texinfo-arg-choice "Encoding" ("US-ASCII" "UTF-8" "ISO-8859-1" "ISO-8859-15" "ISO-8859-2" "koi8-r" "koi8-u")) (Texinfo-arg-next-line))
|
||
|
'("dots" nil)
|
||
|
'("emph" "Text")
|
||
|
'("email" "Email address")
|
||
|
'("equiv" nil)
|
||
|
'("error")
|
||
|
'("evenfooting" Texinfo-arg-lrc)
|
||
|
'("evenheading" Texinfo-arg-lrc)
|
||
|
'("everyfooting" Texinfo-arg-lrc)
|
||
|
'("everyheading" Texinfo-arg-lrc)
|
||
|
'("exdent" (TeX-arg-literal " ") (TeX-arg-free "Line of text"))
|
||
|
'("expansion" nil)
|
||
|
'("file" "Filename")
|
||
|
'("finalout")
|
||
|
'("findex" (TeX-arg-literal " ") (TeX-arg-free "Entry"))
|
||
|
'("footnote" "Text of footnote")
|
||
|
'("footnotestyle" (TeX-arg-literal " ") (TeX-arg-free "Style"))
|
||
|
'("guillemetleft")
|
||
|
'("guillemetright")
|
||
|
'("guilsinglleft")
|
||
|
'("guilsinglright")
|
||
|
'("heading" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
;; XXX: Would be nice with completion.
|
||
|
'("headings" (TeX-arg-literal " ") (TeX-arg-free "On off single double"))
|
||
|
'("i" "Text")
|
||
|
'("ignore")
|
||
|
'("include" (TeX-arg-literal " ") (TeX-arg-free "Filename"))
|
||
|
'("inforef" "Node name" "Info file name")
|
||
|
'("item")
|
||
|
'("itemx")
|
||
|
'("kbd" "Keyboard characters")
|
||
|
'("key" "Key name")
|
||
|
'("kindex" (TeX-arg-literal " ") (TeX-arg-free "Entry"))
|
||
|
'("LaTeX" nil)
|
||
|
'("lowersections" 0)
|
||
|
'("majorheading" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("menu")
|
||
|
'("minus")
|
||
|
'("need" "N")
|
||
|
'("node" (TeX-arg-literal " ") (TeX-arg-free "Name")
|
||
|
(TeX-arg-literal ", ") (TeX-arg-free "Next")
|
||
|
(TeX-arg-literal ", ") (TeX-arg-free "Previous")
|
||
|
(TeX-arg-literal ", ") (TeX-arg-free "Up"))
|
||
|
'("noindent")
|
||
|
'("oddfooting" Texinfo-arg-lrc)
|
||
|
'("oddheading" Texinfo-arg-lrc)
|
||
|
'("page")
|
||
|
'("paragraphindent" (TeX-arg-literal " ") (TeX-arg-free "Indent"))
|
||
|
'("pindex" "Entry")
|
||
|
'("point" nil)
|
||
|
'("print")
|
||
|
'("printindex" (TeX-arg-literal " ") (TeX-arg-free "Index name"))
|
||
|
'("pxref" (Texinfo-arg-nodename "Node name"))
|
||
|
'("quotedblbase")
|
||
|
'("quotesinglbase")
|
||
|
'("r" "Text")
|
||
|
'("raisesections" 0)
|
||
|
'("ref" (Texinfo-arg-nodename "Node name"))
|
||
|
'("refill")
|
||
|
'("result")
|
||
|
'("samp" "Text")
|
||
|
'("sc" "Text")
|
||
|
'("section" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("set" (TeX-arg-literal " ") (TeX-arg-free "Flag"))
|
||
|
'("setchapternewpage" (TeX-arg-literal " ") (Texinfo-arg-choice "On off odd" ("on" "off" "odd")) (Texinfo-arg-next-line))
|
||
|
'("setfilename" (TeX-arg-literal " ") (TeX-arg-free "Info file name"))
|
||
|
'("settitle" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("shortcontents")
|
||
|
'("smallbook")
|
||
|
'("sp" "N")
|
||
|
'("strong" "Text")
|
||
|
'("subheading" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("subsection" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("subsubheading" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("subsubsection" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("subtitle" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("summarycontents")
|
||
|
'("syncodeindex" (TeX-arg-literal " ") (TeX-arg-free "From index")
|
||
|
(TeX-arg-literal " ") (TeX-arg-free "Into index"))
|
||
|
'("synindex" (TeX-arg-literal " ") (TeX-arg-free "From index")
|
||
|
(TeX-arg-literal " ") (TeX-arg-free "Into index"))
|
||
|
'("t" "Text")
|
||
|
'("TeX" nil)
|
||
|
'("thischapter")
|
||
|
'("thischaptername")
|
||
|
'("thisfile")
|
||
|
'("thispage")
|
||
|
'("tie")
|
||
|
'("tindex" (TeX-arg-literal " ") (TeX-arg-free "Entry"))
|
||
|
'("title" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("titlefont" "Text")
|
||
|
'("titlepage")
|
||
|
'("today" nil)
|
||
|
'("top" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("unnumbered" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("unnumberedsec" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("unnumberedsubsec" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("unnumberedsubsubsec" (TeX-arg-literal " ") (TeX-arg-free "Title"))
|
||
|
'("url" "Link")
|
||
|
'("value" "Flag")
|
||
|
'("var" "Metasyntactic variable")
|
||
|
'("vindex" (TeX-arg-literal " ") (TeX-arg-free "Entry"))
|
||
|
'("vskip" (TeX-arg-literal " ") (TeX-arg-free "Amount"))
|
||
|
'("w" "Text")
|
||
|
'("xref" (Texinfo-arg-nodename "Node name")))
|
||
|
|
||
|
;; RefTeX plugging
|
||
|
(add-hook 'reftex-mode-hook #'Texinfo-reftex-hook)
|
||
|
(if (and (boundp 'reftex-mode) reftex-mode)
|
||
|
(Texinfo-reftex-hook))
|
||
|
|
||
|
(run-mode-hooks 'text-mode-hook 'Texinfo-mode-hook)
|
||
|
(TeX-set-mode-name))
|
||
|
|
||
|
(defcustom Texinfo-clean-intermediate-suffixes
|
||
|
'("\\.cps?" "\\.vrs?" "\\.fns?" "\\.tps?" "\\.pgs?" "\\.kys?")
|
||
|
"List of regexps matching suffixes of files to be deleted.
|
||
|
The regexps will be anchored at the end of the file name to be matched,
|
||
|
that is, you do _not_ have to cater for this yourself by adding \\\\\\=' or $."
|
||
|
:type '(repeat regexp)
|
||
|
:group 'TeX-command)
|
||
|
|
||
|
(defcustom Texinfo-clean-output-suffixes
|
||
|
;; See `man texi2html' for the HTML stuff.
|
||
|
'("\\.info\\(-[0-9]+\\)?" "\\.dvi" "\\.pdf" "\\.ps" "\\.html"
|
||
|
"_toc\\.html" "_fot\\.html" "_abt\\.html" "_[0-9]+\\.html" "_l2h_img.+")
|
||
|
"List of regexps matching suffixes of files to be deleted.
|
||
|
The regexps will be anchored at the end of the file name to be matched,
|
||
|
that is, you do _not_ have to cater for this yourself by adding \\\\\\=' or $."
|
||
|
:type '(repeat regexp)
|
||
|
:group 'TeX-command)
|
||
|
|
||
|
(provide 'tex-info)
|
||
|
|
||
|
;;; tex-info.el ends here
|