diff options
Diffstat (limited to 'texinfo/emacs/texinfo.el')
-rw-r--r-- | texinfo/emacs/texinfo.el | 932 |
1 files changed, 932 insertions, 0 deletions
diff --git a/texinfo/emacs/texinfo.el b/texinfo/emacs/texinfo.el new file mode 100644 index 00000000000..0a1ab13401e --- /dev/null +++ b/texinfo/emacs/texinfo.el @@ -0,0 +1,932 @@ +;;; texinfo.el--major mode for editing Texinfo files. + +;; Copyright (C) 1985, '88, '89, '90, '91, +;; '92, '93, '96 Free Software Foundation, Inc. + +;; Author: Robert J. Chassell +;; Date: 6 Sep 1996 +;; Maintainer: bug-texinfo@prep.ai.mit.edu +;; Keywords: maint, tex, docs + +;; This file is part of GNU Emacs. + +;; GNU Emacs 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 2, or (at your option) +;; any later version. + +;; GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + + +;;; Autoloads: + +(autoload 'makeinfo-region + "makeinfo" + "Make Info file from region of current Texinfo file, and switch to it. + +This command does not offer the `next-error' feature since it would +apply to a temporary file, not the original; use the `makeinfo-buffer' +command to gain use of `next-error'." + t nil) + +(autoload 'makeinfo-buffer + "makeinfo" + "Make Info file from current buffer. + +Use the \\[next-error] command to move to the next error +\(if there are errors\)." + t nil) + +(autoload 'kill-compilation + "compile" + "Kill the process made by the \\[compile] command." + t nil) + +(autoload 'makeinfo-recenter-compilation-buffer + "makeinfo" + "Redisplay `*compilation*' buffer so most recent output can be seen. +The last line of the buffer is displayed on +line LINE of the window, or centered if LINE is nil." + t nil) + +(autoload 'texinfo-update-node + "texnfo-upd" + "Without any prefix argument, update the node in which point is located. +Non-nil argument (prefix, if interactive) means update the nodes in the +marked region. + +The functions for creating or updating nodes and menus, and their +keybindings, are: + + texinfo-update-node (&optional region-p) \\[texinfo-update-node] + texinfo-every-node-update () \\[texinfo-every-node-update] + texinfo-sequential-node-update (&optional region-p) + + texinfo-make-menu (&optional region-p) \\[texinfo-make-menu] + texinfo-all-menus-update () \\[texinfo-all-menus-update] + texinfo-master-menu () + + texinfo-indent-menu-description (column &optional region-p) + +The `texinfo-column-for-description' variable specifies the column to +which menu descriptions are indented. Its default value is 32." + t nil) + +(autoload 'texinfo-every-node-update + "texnfo-upd" + "Update every node in a Texinfo file." + t nil) + +(autoload 'texinfo-sequential-node-update + "texnfo-upd" + "Update one node (or many) in a Texinfo file with sequential pointers. + +This function causes the `Next' or `Previous' pointer to point to the +immediately preceding or following node, even if it is at a higher or +lower hierarchical level in the document. Continually pressing `n' or +`p' takes you straight through the file. + +Without any prefix argument, update the node in which point is located. +Non-nil argument (prefix, if interactive) means update the nodes in the +marked region. + +This command makes it awkward to navigate among sections and +subsections; it should be used only for those documents that are meant +to be read like a novel rather than a reference, and for which the +Info `g*' command is inadequate." + t nil) + +(autoload 'texinfo-make-menu + "texnfo-upd" + "Without any prefix argument, make or update a menu. +Make the menu for the section enclosing the node found following point. + +Non-nil argument (prefix, if interactive) means make or update menus +for nodes within or part of the marked region. + +Whenever a menu exists, and is being updated, the descriptions that +are associated with node names in the pre-existing menu are +incorporated into the new menu. Otherwise, the nodes' section titles +are inserted as descriptions." + t nil) + +(autoload 'texinfo-all-menus-update + "texnfo-upd" + "Update every regular menu in a Texinfo file. +Remove pre-existing master menu, if there is one. + +If called with a non-nil argument, this function first updates all the +nodes in the buffer before updating the menus." + t nil) + +(autoload 'texinfo-master-menu + "texnfo-upd" + "Make a master menu for a whole Texinfo file. +Non-nil argument (prefix, if interactive) means first update all +existing nodes and menus. Remove pre-existing master menu, if there is one. + +This function creates a master menu that follows the top node. The +master menu includes every entry from all the other menus. It +replaces any existing ordinary menu that follows the top node. + +If called with a non-nil argument, this function first updates all the +menus in the buffer (incorporating descriptions from pre-existing +menus) before it constructs the master menu. + +The function removes the detailed part of an already existing master +menu. This action depends on the pre-existing master menu using the +standard `texinfo-master-menu-header'. + +The master menu has the following format, which is adapted from the +recommendation in the Texinfo Manual: + + * The first part contains the major nodes in the Texinfo file: the + nodes for the chapters, chapter-like sections, and the major + appendices. This includes the indices, so long as they are in + chapter-like sections, such as unnumbered sections. + + * The second and subsequent parts contain a listing of the other, + lower level menus, in order. This way, an inquirer can go + directly to a particular node if he or she is searching for + specific information. + +Each of the menus in the detailed node listing is introduced by the +title of the section containing the menu." + t nil) + +(autoload 'texinfo-indent-menu-description + "texnfo-upd" + "Indent every description in menu following point to COLUMN. +Non-nil argument (prefix, if interactive) means indent every +description in every menu in the region. Does not indent second and +subsequent lines of a multi-line description." + t nil) + +(autoload 'texinfo-insert-node-lines + "texnfo-upd" + "Insert missing `@node' lines in region of Texinfo file. +Non-nil argument (prefix, if interactive) means also to insert the +section titles as node names; and also to insert the section titles as +node names in pre-existing @node lines that lack names." + t nil) + +(autoload 'texinfo-start-menu-description + "texnfo-upd" + "In this menu entry, insert the node's section title as a description. +Position point at beginning of description ready for editing. +Do not insert a title if the line contains an existing description. + +You will need to edit the inserted text since a useful description +complements the node name rather than repeats it as a title does." + t nil) + +(autoload 'texinfo-multiple-files-update + "texnfo-upd" + "Update first node pointers in each file included in OUTER-FILE; +create or update main menu in the outer file that refers to such nodes. +This does not create or update menus or pointers within the included files. + +With optional MAKE-MASTER-MENU argument (prefix arg, if interactive), +insert a master menu in OUTER-FILE. This does not create or update +menus or pointers within the included files. + +With optional UPDATE-EVERYTHING argument (numeric prefix arg, if +interactive), update all the menus and all the `Next', `Previous', and +`Up' pointers of all the files included in OUTER-FILE before inserting +a master menu in OUTER-FILE. + +The command also updates the `Top' level node pointers of OUTER-FILE. + +Notes: + + * this command does NOT save any files--you must save the + outer file and any modified, included files. + + * except for the `Top' node, this command does NOT handle any + pre-existing nodes in the outer file; hence, indices must be + enclosed in an included file. + +Requirements: + + * each of the included files must contain exactly one highest + hierarchical level node, + * this highest node must be the first node in the included file, + * each highest hierarchical level node must be of the same type. + +Thus, normally, each included file contains one, and only one, +chapter." + t nil) + + +;;; Code: + +;;; Don't you dare insert any `require' calls at top level in this file--rms. + +;;; Syntax table + +(defvar texinfo-mode-syntax-table nil) + +(if texinfo-mode-syntax-table + nil + (setq texinfo-mode-syntax-table (make-syntax-table)) + (modify-syntax-entry ?\" " " texinfo-mode-syntax-table) + (modify-syntax-entry ?\\ " " texinfo-mode-syntax-table) + (modify-syntax-entry ?@ "\\" texinfo-mode-syntax-table) + (modify-syntax-entry ?\^q "\\" texinfo-mode-syntax-table) + (modify-syntax-entry ?\[ "(]" texinfo-mode-syntax-table) + (modify-syntax-entry ?\] ")[" texinfo-mode-syntax-table) + (modify-syntax-entry ?{ "(}" texinfo-mode-syntax-table) + (modify-syntax-entry ?} "){" texinfo-mode-syntax-table) + (modify-syntax-entry ?\' "w" texinfo-mode-syntax-table)) + +;; Written by Wolfgang Bangerth <zcg51122@rpool1.rus.uni-stuttgart.de> +;; To override this example, set either `imenu-generic-expression' +;; or `imenu-create-index-function'. +(defvar texinfo-imenu-generic-expression + '((nil "^@node[ \t]+\\([^,\n]*\\)" 1) + ("Chapters" "^@chapter[ \t]+\\(.*\\)$" 1)) + + "Imenu generic expression for TexInfo mode. See `imenu-generic-expression'.") + +(defvar texinfo-font-lock-keywords + '(;; All but the first 2 had an OVERRIDE of t. + ;; It didn't seem to be any better, and it's slower--simon. + ("^\\(@c\\|@comment\\)\\>.*" . font-lock-comment-face) ;comments + ;; Robert J. Chassell <bob@gnu.ai.mit.edu> says remove this line. + ;("\\$\\([^$]*\\)\\$" 1 font-lock-string-face t) + ("@\\([a-zA-Z]+\\|[^ \t\n]\\)" 1 font-lock-keyword-face) ;commands + ("^\\*\\(.*\\)[\t ]*$" 1 font-lock-function-name-face t) ;menu items + ("@\\(emph\\|strong\\|b\\|i\\){\\([^}]+\\)" 2 font-lock-comment-face) + ("@\\(file\\|kbd\\|key\\){\\([^}]+\\)" 2 font-lock-string-face) + ("@\\(samp\\|code\\|var\\|math\\){\\([^}]+\\)" + 2 font-lock-variable-name-face) + ("@\\(cite\\|xref\\|pxref\\){\\([^}]+\\)" 2 font-lock-reference-face) + ("@\\(end\\|itemx?\\) +\\(.+\\)" 2 font-lock-function-name-face keep) + ) + "Additional expressions to highlight in TeXinfo mode.") + +(defvar texinfo-section-list + '(("top" 1) + ("majorheading" 1) + ("chapter" 2) + ("unnumbered" 2) + ("appendix" 2) + ("chapheading" 2) + ("section" 3) + ("unnumberedsec" 3) + ("appendixsec" 3) + ("heading" 3) + ("subsection" 4) + ("unnumberedsubsec" 4) + ("appendixsubsec" 4) + ("subheading" 4) + ("subsubsection" 5) + ("unnumberedsubsubsec" 5) + ("appendixsubsubsec" 5) + ("subsubheading" 5)) + "Alist of sectioning commands and their relative level.") + +(defun texinfo-outline-level () + ;; Calculate level of current texinfo outline heading. + (save-excursion + (if (bobp) + 0 + (forward-char 1) + (let* ((word (buffer-substring-no-properties + (point) (progn (forward-word 1) (point)))) + (entry (assoc word texinfo-section-list))) + (if entry + (nth 1 entry) + 5))))) + + +;;; Keybindings +(defvar texinfo-mode-map nil) + +;;; Keys common both to Texinfo mode and to TeX shell. + +(defun texinfo-define-common-keys (keymap) + "Define the keys both in Texinfo mode and in the texinfo-tex-shell." + (define-key keymap "\C-c\C-t\C-k" 'tex-kill-job) + (define-key keymap "\C-c\C-t\C-x" 'texinfo-quit-job) + (define-key keymap "\C-c\C-t\C-l" 'tex-recenter-output-buffer) + (define-key keymap "\C-c\C-t\C-d" 'texinfo-delete-from-print-queue) + (define-key keymap "\C-c\C-t\C-q" 'tex-show-print-queue) + (define-key keymap "\C-c\C-t\C-p" 'texinfo-tex-print) + (define-key keymap "\C-c\C-t\C-i" 'texinfo-texindex) + + (define-key keymap "\C-c\C-t\C-r" 'texinfo-tex-region) + (define-key keymap "\C-c\C-t\C-b" 'texinfo-tex-buffer)) + +;; Mode documentation displays commands in reverse order +;; from how they are listed in the texinfo-mode-map. + +(if texinfo-mode-map + nil + (setq texinfo-mode-map (make-sparse-keymap)) + + ;; bindings for `texnfo-tex.el' + (texinfo-define-common-keys texinfo-mode-map) + + ;; bindings for `makeinfo.el' + (define-key texinfo-mode-map "\C-c\C-m\C-k" 'kill-compilation) + (define-key texinfo-mode-map "\C-c\C-m\C-l" + 'makeinfo-recenter-compilation-buffer) + (define-key texinfo-mode-map "\C-c\C-m\C-r" 'makeinfo-region) + (define-key texinfo-mode-map "\C-c\C-m\C-b" 'makeinfo-buffer) + + ;; bindings for `texinfmt.el' + (define-key texinfo-mode-map "\C-c\C-e\C-r" 'texinfo-format-region) + (define-key texinfo-mode-map "\C-c\C-e\C-b" 'texinfo-format-buffer) + + ;; bindings for updating nodes and menus + + (define-key texinfo-mode-map "\C-c\C-um" 'texinfo-master-menu) + + (define-key texinfo-mode-map "\C-c\C-u\C-m" 'texinfo-make-menu) + (define-key texinfo-mode-map "\C-c\C-u\C-n" 'texinfo-update-node) + (define-key texinfo-mode-map "\C-c\C-u\C-e" 'texinfo-every-node-update) + (define-key texinfo-mode-map "\C-c\C-u\C-a" 'texinfo-all-menus-update) + + (define-key texinfo-mode-map "\C-c\C-s" 'texinfo-show-structure) + + (define-key texinfo-mode-map "\C-c}" 'up-list) + (define-key texinfo-mode-map "\C-c]" 'up-list) + (define-key texinfo-mode-map "\C-c{" 'texinfo-insert-braces) + + ;; bindings for inserting strings + + (define-key texinfo-mode-map "\C-c\C-c\C-d" 'texinfo-start-menu-description) + + (define-key texinfo-mode-map "\C-c\C-cv" 'texinfo-insert-@var) + (define-key texinfo-mode-map "\C-c\C-ct" 'texinfo-insert-@table) + (define-key texinfo-mode-map "\C-c\C-cs" 'texinfo-insert-@samp) + (define-key texinfo-mode-map "\C-c\C-co" 'texinfo-insert-@noindent) + (define-key texinfo-mode-map "\C-c\C-cn" 'texinfo-insert-@node) + (define-key texinfo-mode-map "\C-c\C-ck" 'texinfo-insert-@kbd) + (define-key texinfo-mode-map "\C-c\C-ci" 'texinfo-insert-@item) + (define-key texinfo-mode-map "\C-c\C-cf" 'texinfo-insert-@file) + (define-key texinfo-mode-map "\C-c\C-cx" 'texinfo-insert-@example) + (define-key texinfo-mode-map "\C-c\C-ce" 'texinfo-insert-@end) + (define-key texinfo-mode-map "\C-c\C-cd" 'texinfo-insert-@dfn) + (define-key texinfo-mode-map "\C-c\C-cc" 'texinfo-insert-@code)) + + +;;; Texinfo mode + +(defvar texinfo-chapter-level-regexp + "chapter\\|unnumbered \\|appendix \\|majorheading\\|chapheading" + "Regular expression matching Texinfo chapter-level headings. +This does not match `@node' and does not match the `@top' command.") + +;;;###autoload +(defun texinfo-mode () + "Major mode for editing Texinfo files. + + It has these extra commands: +\\{texinfo-mode-map} + + These are files that are used as input for TeX to make printed manuals +and also to be turned into Info files with \\[makeinfo-buffer] or +the `makeinfo' program. These files must be written in a very restricted and +modified version of TeX input format. + + Editing commands are like text-mode except that the syntax table is +set up so expression commands skip Texinfo bracket groups. To see +what the Info version of a region of the Texinfo file will look like, +use \\[makeinfo-region], which runs `makeinfo' on the current region. + + You can show the structure of a Texinfo file with \\[texinfo-show-structure]. +This command shows the structure of a Texinfo file by listing the +lines with the @-sign commands for @chapter, @section, and the like. +These lines are displayed in another window called the *Occur* window. +In that window, you can position the cursor over one of the lines and +use \\[occur-mode-goto-occurrence], to jump to the corresponding spot +in the Texinfo file. + + In addition, Texinfo mode provides commands that insert various +frequently used @-sign commands into the buffer. You can use these +commands to save keystrokes. And you can insert balanced braces with +\\[texinfo-insert-braces] and later use the command \\[up-list] to +move forward past the closing brace. + +Also, Texinfo mode provides functions for automatically creating or +updating menus and node pointers. These functions + + * insert the `Next', `Previous' and `Up' pointers of a node, + * insert or update the menu for a section, and + * create a master menu for a Texinfo source file. + +Here are the functions: + + texinfo-update-node \\[texinfo-update-node] + texinfo-every-node-update \\[texinfo-every-node-update] + texinfo-sequential-node-update + + texinfo-make-menu \\[texinfo-make-menu] + texinfo-all-menus-update \\[texinfo-all-menus-update] + texinfo-master-menu + + texinfo-indent-menu-description (column &optional region-p) + +The `texinfo-column-for-description' variable specifies the column to +which menu descriptions are indented. + +Passed an argument (a prefix argument, if interactive), the +`texinfo-update-node' and `texinfo-make-menu' functions do their jobs +in the region. + +To use the updating commands, you must structure your Texinfo file +hierarchically, such that each `@node' line, with the exception of the +Top node, is accompanied by some kind of section line, such as an +`@chapter' or `@section' line. + +If the file has a `top' node, it must be called `top' or `Top' and +be the first node in the file. + +Entering Texinfo mode calls the value of text-mode-hook, and then the +value of texinfo-mode-hook." + (interactive) + (text-mode) + (setq mode-name "Texinfo") + (setq major-mode 'texinfo-mode) + (use-local-map texinfo-mode-map) + (set-syntax-table texinfo-mode-syntax-table) + (make-local-variable 'page-delimiter) + (setq page-delimiter + (concat + "^@node [ \t]*[Tt]op\\|^@\\(" + texinfo-chapter-level-regexp + "\\)")) + (make-local-variable 'require-final-newline) + (setq require-final-newline t) + (make-local-variable 'indent-tabs-mode) + (setq indent-tabs-mode nil) + (make-local-variable 'paragraph-separate) + (setq paragraph-separate (concat "^\b\\|^@[a-zA-Z]*[ \n]\\|" paragraph-separate)) + (make-local-variable 'paragraph-start) + (setq paragraph-start (concat "^\b\\|^@[a-zA-Z]*[ \n]\\|" paragraph-start)) + (make-local-variable 'fill-column) + (setq fill-column 72) + (make-local-variable 'comment-start) + (setq comment-start "@c ") + (make-local-variable 'comment-start-skip) + (setq comment-start-skip "@c +") + (make-local-variable 'words-include-escapes) + (setq words-include-escapes t) + (make-local-variable 'imenu-generic-expression) + (setq imenu-generic-expression texinfo-imenu-generic-expression) + (make-local-variable 'font-lock-defaults) + (setq font-lock-defaults '(texinfo-font-lock-keywords t)) + (make-local-variable 'outline-regexp) + (setq outline-regexp + (concat "@\\(" + (mapconcat 'car texinfo-section-list "\\>\\|") + "\\>\\)")) + (make-local-variable 'outline-level) + (setq outline-level 'texinfo-outline-level) + (make-local-variable 'tex-start-of-header) + (setq tex-start-of-header "%**start") + (make-local-variable 'tex-end-of-header) + (setq tex-end-of-header "%**end") + (run-hooks 'text-mode-hook 'texinfo-mode-hook)) + + +;;; Insert string commands + +;; Keep as concatinated lists for ease of maintenance +(defconst texinfo-environment-regexp + (concat + "^@" + "\\(" + "cartouche\\|" + "display\\|" + "end\\|" + "enumerate\\|" + "example\\|" + "f?table\\|" + "flushleft\\|" + "flushright\\|" + "format\\|" + "group\\|" + "ifhtml\\|" + "ifinfo\\|" + "iftex\\|" + "ignore\\|" + "itemize\\|" + "lisp\\|" + "macro\\|" + "multitable\\|" + "quotation\\|" + "smallexample\\|" + "smalllisp\\|" + "tex" + "\\)") + "Regexp for environment-like TexInfo list commands. + Subexpression 1 is what goes into the corresponding `@end' statement.") + +;; The following texinfo-insert-@end command not only inserts a SPC +;; after the @end, but tries to find out what belongs there. It is +;; not very smart: it does not understand nested lists. + +(defun texinfo-insert-@end () + "Insert the matching `@end' for the last Texinfo command that needs one." + (interactive) + (let ((depth 1) string) + (save-excursion + (while (and (> depth 0) + (re-search-backward texinfo-environment-regexp nil t) + (if (looking-at "@end") + (setq depth (1+ depth)) + (setq depth (1- depth))))) + (looking-at texinfo-environment-regexp) + (if (zerop depth) + (setq string + (buffer-substring (match-beginning 1) + (match-end 1))))) + (insert "@end ") + (if string (insert string "\n")))) + +;; The following insert commands accept a prefix arg N, which is the +;; number of words (actually s-exprs) that should be surrounded by +;; braces. Thus you can first paste a variable name into a .texinfo +;; buffer, then say C-u 1 C-c C-c v at the beginning of the just +;; pasted variable name to put @var{...} *around* the variable name. +;; Operate on previous word or words with negative arg. + +;; These commands use texinfo-insert-@-with-arg +(defun texinfo-insert-@-with-arg (string &optional arg) + (if arg + (progn + (setq arg (prefix-numeric-value arg)) + (if (< arg 0) + (progn + (skip-chars-backward " \t\n\r\f") + (save-excursion + (forward-sexp arg) + (insert "@" string "{")) + (insert "}")) + (skip-chars-forward " \t\n\r\f") + (insert "@" string "{") + (forward-sexp arg) + (insert "}"))) + (insert "@" string "{}") + (backward-char))) + +(defun texinfo-insert-braces () + "Make a pair of braces and be poised to type inside of them. +Use \\[up-list] to move forward out of the braces." + (interactive) + (insert "{}") + (backward-char)) + +(defun texinfo-insert-@code (&optional arg) + "Insert a `@code{...}' command in a Texinfo buffer. +A numeric argument says how many words the braces should surround. +The default is not to surround any existing words with the braces." + (interactive "P") + (texinfo-insert-@-with-arg "code" arg)) + +(defun texinfo-insert-@dfn (&optional arg) + "Insert a `@dfn{...}' command in a Texinfo buffer. +A numeric argument says how many words the braces should surround. +The default is not to surround any existing words with the braces." + (interactive "P") + (texinfo-insert-@-with-arg "dfn" arg)) + +(defun texinfo-insert-@example () + "Insert the string `@example' in a Texinfo buffer." + (interactive) + (insert "@example\n")) + +(defun texinfo-insert-@file (&optional arg) + "Insert a `@file{...}' command in a Texinfo buffer. +A numeric argument says how many words the braces should surround. +The default is not to surround any existing words with the braces." + (interactive "P") + (texinfo-insert-@-with-arg "file" arg)) + +(defun texinfo-insert-@item () + "Insert the string `@item' in a Texinfo buffer." + (interactive) + (insert "@item") + (newline)) + +(defun texinfo-insert-@kbd (&optional arg) + "Insert a `@kbd{...}' command in a Texinfo buffer. +A numeric argument says how many words the braces should surround. +The default is not to surround any existing words with the braces." + (interactive "P") + (texinfo-insert-@-with-arg "kbd" arg)) + +(defun texinfo-insert-@node () + "Insert the string `@node' in a Texinfo buffer. +This also inserts on the following line a comment indicating +the order of arguments to @node." + (interactive) + (insert "@node \n@comment node-name, next, previous, up") + (forward-line -1) + (forward-char 6)) + +(defun texinfo-insert-@noindent () + "Insert the string `@noindent' in a Texinfo buffer." + (interactive) + (insert "@noindent\n")) + +(defun texinfo-insert-@samp (&optional arg) + "Insert a `@samp{...}' command in a Texinfo buffer. +A numeric argument says how many words the braces should surround. +The default is not to surround any existing words with the braces." + (interactive "P") + (texinfo-insert-@-with-arg "samp" arg)) + +(defun texinfo-insert-@table (&optional arg) + "Insert the string `@table' in a Texinfo buffer." + (interactive "P") + (insert "@table ")) + +(defun texinfo-insert-@var (&optional arg) + "Insert a `@var{}' command in a Texinfo buffer. +A numeric argument says how many words the braces should surround. +The default is not to surround any existing words with the braces." + (interactive "P") + (texinfo-insert-@-with-arg "var" arg)) + +;;; Texinfo file structure + +;; These are defined in texnfo-upd.el. +;; texinfo-section-types-regexp +;; texinfo-section-level-regexp +;; texinfo-subsection-level-regexp +;; texinfo-subsubsection-level-regexp + +;; `texinfo-show-structure' requires texnfo-upd.el +(defun texinfo-show-structure (&optional nodes-too) + "Show the structure of a Texinfo file. +List the lines in the file that begin with the @-sign commands for +@chapter, @section, and the like. + +With optional argument (prefix if interactive), list both the lines +with @-sign commands for @chapter, @section, and the like, and list +@node lines. + +Lines with structuring commands beginning in them are displayed in +another buffer named `*Occur*'. In that buffer, you can move point to +one of those lines and then use \\<occur-mode-map>\\[occur-mode-goto-occurrence], +to jump to the corresponding spot in the Texinfo source file." + + (interactive "P") + (require 'texnfo-upd) + (save-excursion + (goto-char (point-min)) + (if nodes-too + (occur (concat "\\(^@node\\)\\|" texinfo-section-types-regexp)) + (occur texinfo-section-types-regexp))) + (pop-to-buffer "*Occur*") + (goto-char (point-min)) + (flush-lines "-----") + ;; Now format the "*Occur*" buffer to show the structure. + ;; Thanks to ceder@signum.se (Per Cederqvist) + (goto-char (point-max)) + (let ((margin 5)) + (while (re-search-backward "^ *[0-9]*:" nil 0) + (re-search-forward ":") + (setq margin + (cond + ((looking-at + (concat "@\\(" texinfo-chapter-level-regexp "\\)")) 5) + ;; ((looking-at "@chapter ") 5) + ;; ((looking-at "@unnumbered ") 5) + ;; ((looking-at "@appendix ") 5) + ;; ((looking-at "@majorheading ") 5) + ;; ((looking-at "@chapheading ") 5) + + ((looking-at + (concat "@\\(" texinfo-section-level-regexp "\\)")) 9) + ;; ((looking-at "@section ") 9) + ;; ((looking-at "@unnumberedsec ") 9) + ;; ((looking-at "@appendixsec ") 9) + ;; ((looking-at "@heading ") 9) + + ((looking-at + (concat "@\\(" texinfo-subsection-level-regexp "\\)")) 13) + ;; ((looking-at "@subsection ") 13) + ;; ((looking-at "@unnumberedsubsec ") 13) + ;; ((looking-at "@appendixsubsec ") 13) + ;; ((looking-at "@subheading ") 13) + + ((looking-at + (concat "@\\(" texinfo-subsubsection-level-regexp "\\)")) 17) + ;; ((looking-at "@subsubsection ") 17) + ;; ((looking-at "@unnumberedsubsubsec ") 17) + ;; ((looking-at "@appendixsubsubsec ") 17) + ;; ((looking-at "@subsubheading ") 17) + (t margin))) + (indent-to-column margin) + (beginning-of-line)))) + +;;; The tex and print function definitions: + +(defvar texinfo-texi2dvi-command "texi2dvi" + "*Command used by `texinfo-tex-buffer' to run TeX and texindex on a buffer.") + +(defvar texinfo-tex-command "tex" + "*Command used by `texinfo-tex-region' to run TeX on a region.") + +(defvar texinfo-texindex-command "texindex" + "*Command used by `texinfo-texindex' to sort unsorted index files.") + +(defvar texinfo-delete-from-print-queue-command "lprm" + "*Command string used to delete a job from the line printer queue. +Command is used by \\[texinfo-delete-from-print-queue] based on +number provided by a previous \\[tex-show-print-queue] +command.") + +(defvar texinfo-tex-trailer "@bye" + "String appended after a region sent to TeX by `texinfo-tex-region'.") + +(defun texinfo-tex-region (beg end) + "Run TeX on the current region. +This works by writing a temporary file (`tex-zap-file') in the directory +that is the value of `tex-directory', then running TeX on that file. + +The first line of the buffer is copied to the +temporary file; and if the buffer has a header, it is written to the +temporary file before the region itself. The buffer's header is all lines +between the strings defined by `tex-start-of-header' and `tex-end-of-header' +inclusive. The header must start in the first 100 lines. + +The value of `texinfo-tex-trailer' is appended to the temporary file after the region." + (interactive "r") + (require 'tex-mode) + (if (get-buffer "*tex-shell*") + (tex-kill-job) + (tex-start-shell)) + (or tex-zap-file (setq tex-zap-file (make-temp-name "#tz"))) + (let ((tex-out-file (concat tex-zap-file ".tex")) + (temp-buffer (get-buffer-create " tex-Output-Buffer")) + (zap-directory + (file-name-as-directory (expand-file-name tex-directory)))) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (forward-line 100) + (let ((search-end (point)) + (hbeg (point-min)) (hend (point-min)) + (default-directory zap-directory)) + (goto-char (point-min)) + + ;; Copy first line, the `\input texinfo' line, to temp file + (write-region (point) + (save-excursion (end-of-line) (point)) + tex-out-file nil nil) + + ;; Don't copy first line twice if region includes it. + (forward-line 1) + (if (< beg (point)) (setq beg (point))) + + ;; Initialize the temp file with either the header or nothing + (if (search-forward tex-start-of-header search-end t) + (progn + (beginning-of-line) + (setq hbeg (point)) ; Mark beginning of header. + (if (search-forward tex-end-of-header nil t) + (progn (beginning-of-line) + (setq hend (point))) ; Mark end of header. + (setq hbeg (point-min))))) ; Else no header. + + ;; Copy header to temp file. + (write-region (min hbeg beg) hend tex-out-file t nil) + + ;; Copy region to temp file. + (write-region (max beg hend) end tex-out-file t nil)) + + ;; This is a kludge to insert the tex-trailer into the tex-out-file. + ;; We have to create a special buffer in which to insert + ;; the tex-trailer first because there is no function with + ;; which to append a literal string directly to a file. + (let ((local-tex-trailer texinfo-tex-trailer)) + (set-buffer temp-buffer) + (erase-buffer) + ;; make sure trailer isn't hidden by a comment + (insert-string "\n") + (if local-tex-trailer (insert-string local-tex-trailer)) + (tex-set-buffer-directory temp-buffer zap-directory) + (write-region (point-min) (point-max) tex-out-file t nil)) + +;;; The following is sufficient in Emacs 19. +;;; (write-region (concat "\n" texinfo-tex-trailer) nil +;;; tex-out-file t nil) + )) + + (tex-set-buffer-directory "*tex-shell*" zap-directory) + (tex-send-command tex-shell-cd-command zap-directory) + (tex-send-command texinfo-tex-command tex-out-file) + ;; alternatively: + ;; (send-string "tex-shell" (concat tex-shell-cd-command " " + ;; zap-directory "\n")) + ;; (send-string "tex-shell" (concat texinfo-tex-command " " + ;; tex-out-file "\n")) + (tex-recenter-output-buffer 0))) + +(defun texinfo-tex-buffer () + "Run TeX on visited file, once or twice, to make a correct `.dvi' file." + (interactive) + + ;; Make sure TeX shell is running. + (require 'tex-mode) + (if (get-buffer "*tex-shell*") + (quit-process (get-process "tex-shell") t) + (tex-start-shell)) + + (cond ((null buffer-file-name) + (error "Buffer not visiting any file!")) + ((buffer-modified-p) + (error "Buffer has been modified since last saved!"))) + + (setq tex-zap-file buffer-file-name) + + (tex-send-command tex-shell-cd-command (file-name-directory tex-zap-file)) + + (tex-send-command texinfo-texi2dvi-command tex-zap-file) + + ;; alternatively: + ;; (send-string "tex-shell" + ;; (concat tex-shell-cd-command + ;; " " (file-name-directory tex-zap-file) "\n")) + ;; ) + ;; + ;; (send-string "tex-shell" + ;; (concat texinfo-texi2dvi-command " " tex-zap-file "\n")) + + + (tex-recenter-output-buffer 0)) + +(defun texinfo-texindex () + "Run `texindex' on unsorted index files. +The index files are made by \\[texinfo-tex-region] or \\[texinfo-tex-buffer]. +This runs the shell command defined by `texinfo-texindex-command'." + (interactive) + (require 'tex-mode) + (tex-send-command texinfo-texindex-command (concat tex-zap-file ".??")) + ;; alternatively + ;; (send-string "tex-shell" + ;; (concat texinfo-texindex-command + ;; " " tex-zap-file ".??" "\n")) + (tex-recenter-output-buffer nil)) + +(defun texinfo-tex-print () + "Print `.dvi' file made by \\[texinfo-tex-region] or \\[texinfo-tex-buffer]. +This runs the shell command defined by `tex-dvi-print-command'." + (interactive) + (require 'tex-mode) + (tex-send-command tex-dvi-print-command (concat tex-zap-file ".dvi")) + ;; alternatively: + ;; (send-string "tex-shell" + ;; (concat tex-dvi-print-command + ;; " " tex-zap-file ".dvi" "\n")) + (tex-recenter-output-buffer nil)) + +(defun texinfo-quit-job () + "Quit currently running TeX job, by sending an `x' to it." + (interactive) + (if (not (get-process "tex-shell")) + (error "No TeX shell running")) + (tex-send-command "x")) +;; alternatively: +;; save-excursion +;; (set-buffer (get-buffer "*tex-shell*")) +;; (goto-char (point-max)) +;; (insert "x") +;; (comint-send-input) + +(defun texinfo-delete-from-print-queue (job-number) + "Delete job from the line printer spooling queue. +You are prompted for the job number (use a number shown by a previous +\\[tex-show-print-queue] command)." + (interactive "nPrinter job number for deletion: ") + (require 'tex-mode) + (if (tex-shell-running) + (tex-kill-job) + (tex-start-shell)) + (tex-send-command texinfo-delete-from-print-queue-command job-number) + ;; alternatively + ;; (send-string "tex-shell" + ;; (concat + ;; texinfo-delete-from-print-queue-command + ;; " " + ;; job-number"\n")) + (tex-recenter-output-buffer nil)) + +(provide 'texinfo) + +;;; texinfo.el ends here |