;; Convert latexinfo files to info files. ;; Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc. ;; Copyleft (C) 1988, 1989, 1990, 1991 Michael E. Clarkson ;; This file is not yet a part of GNU Emacs. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY. No author or distributor ;; accepts responsibility to anyone for the consequences of using it ;; or for whether it serves any particular purpose or works at all, ;; unless he says so in writing. Refer to the GNU Emacs General Public ;; License for full details. ;; Everyone is granted permission to copy, modify and redistribute ;; GNU Emacs, but only under the conditions described in the ;; GNU Emacs General Public License. A copy of this license is ;; supposed to have been given to you along with GNU Emacs so you ;; can know your rights and responsibilities. It should be in a ;; file named COPYING. Among other things, the copyright notice ;; and this notice must be preserved on all copies. (defvar latexinfo-formats-directory (file-name-as-directory (or (getenv "LATEXINFO") "."))) (defvar latexinfo-texinputs (let ((texinputs (or (getenv "TEXINPUTS") (concat ".:" latexinfo-formats-directory ":/usr/local/lib/tex/inputs"))) (dirlist) (i 0) (l) (s) (sepchar ?:)) (if (eq system-type 'vax-vms) (setq sepchar ?,)) ; emacs.c (setq l (length texinputs)) (while (< i l) (setq s i) (while (and (< i l) (not (char-equal (aref texinputs i) sepchar))) (setq i (1+ i))) (if (> i s) (setq dirlist (append dirlist (list (substring texinputs s i))))) (setq i (1+ i))) dirlist)) (defvar latexinfo-always-refill nil) (if (not (memq latexinfo-formats-directory load-path)) (setq load-path (cons latexinfo-formats-directory load-path))) (if (not (memq "." load-path)) ; add the current directory to load-path (setq load-path (cons "." load-path))) (defvar latexinfo-known-document-styles '(latexinfo 11pt 12pt twoside titlepage A4 a4 dina4 psfonts format)) (autoload 'latexinfo-mode "latexnfo-mde" "Major mode for editing latexinfo files." t) (autoload 'Info-tagify "informat" "Info Tagify" t) (autoload 'Info-split "informat" "Info Split" t) (put 'latexinfoversion 'latexinfo-format 'latexinfo-format-latexinfoversion) (defun latexinfo-format-latexinfoversion () (latexinfo-parse-noarg) (insert "1.7")) (defvar latexinfo-vindex-old nil) (defvar latexinfo-findex-old nil) (defvar latexinfo-cindex-old nil) (defvar latexinfo-cpsubindex-old nil) (defvar latexinfo-pindex-old nil) (defvar latexinfo-tindex-old nil) (defvar latexinfo-kindex-old nil) (defvar latexinfo-refindex-old nil) (defvar latexinfo-format-syntax-table nil) (progn (setq latexinfo-format-syntax-table (make-syntax-table)) (modify-syntax-entry ?* "w" latexinfo-format-syntax-table) (modify-syntax-entry ?& "w" latexinfo-format-syntax-table) (modify-syntax-entry ?\\ "\\" latexinfo-format-syntax-table) (modify-syntax-entry ?\^q "\\" latexinfo-format-syntax-table) (modify-syntax-entry ?{ "(}" latexinfo-format-syntax-table) (modify-syntax-entry ?} "){" latexinfo-format-syntax-table) (modify-syntax-entry ?\[ "(]" latexinfo-format-syntax-table) ; changed (modify-syntax-entry ?\] ")[" latexinfo-format-syntax-table) ; changed (modify-syntax-entry ?\" " " latexinfo-format-syntax-table) (modify-syntax-entry ?\( " " latexinfo-format-syntax-table) (modify-syntax-entry ?\) " " latexinfo-format-syntax-table) ;; punctuation characters are important to \alwaysrefill (modify-syntax-entry ?! "." latexinfo-format-syntax-table) (modify-syntax-entry ?. "." latexinfo-format-syntax-table) (modify-syntax-entry ?: "." latexinfo-format-syntax-table) (modify-syntax-entry ?\' "." latexinfo-format-syntax-table) ) (defun latexinfo-format-buffer (&optional notagify) "Process the current buffer as latexinfo code, into an Info file. The Info file output is generated in a buffer visiting the Info file names specified in the \\setfilename command. Non-nil argument (prefix, if interactive) means don't make tag table and don't split the file if large. You can use Info-tagify and Info-split to do these manually. Returns a list: (list outfile latexinfo-cindex latexinfo-vindex latexinfo-findex latexinfo-pindex latexinfo-tindex latexinfo-kindex latexinfo-refindex)" (interactive "P") (let ((lastmessage "Formatting Info file...")) (message lastmessage) (let ((retval (latexinfo-format-buffer-1))) (setq latexinfo-cindex-old (nth 1 retval)) (setq latexinfo-vindex-old (nth 2 retval)) (setq latexinfo-findex-old (nth 3 retval)) (setq latexinfo-pindex-old (nth 4 retval)) (setq latexinfo-tindex-old (nth 5 retval)) (setq latexinfo-kindex-old (nth 6 retval)) (setq latexinfo-refindex-old (nth 7 retval))) (if notagify nil (latexinfo-split)) (if (interactive-p) (message (concat lastmessage "done. Now save it." "done."))))) (defun latexinfo-split () (if (> (buffer-size) 30000) (progn (message (setq lastmessage "Making tags table for Info file...")) (Info-tagify))) (if (> (buffer-size) 100000) (progn (message (setq lastmessage "Splitting Info file...")) (Info-split)))) (defun latexinfo-format-buffer-1 () (let (latexinfo-format-filename latexinfo-example-start latexinfo-command-start latexinfo-command-end latexinfo-command-name latexinfo-last-node latexinfo-last-node-pos latexinfo-vindex latexinfo-findex latexinfo-cindex latexinfo-cpsubindex latexinfo-pindex latexinfo-tindex latexinfo-kindex latexinfo-refindex latexinfo-stack latexinfo-node-names (latexinfo-table-number 0) (latexinfo-footnote-number 0) outfile (fill-column (1- fill-column)) (input-buffer (current-buffer)) (input-directory default-directory)) (save-excursion (goto-char (point-min)) (re-search-forward "^\\\\setfilename") (setq latexinfo-command-end (point)) (setq outfile (latexinfo-parse-line-arg))) (find-file outfile) (latexinfo-mode) (set-syntax-table latexinfo-format-syntax-table) (erase-buffer) (insert-buffer-substring input-buffer) (goto-char (point-min)) (latexinfo-run-documentstyle-hooks) ;; Run this after latexinfo-run-documentstyle-hooks (goto-char (point-min)) (re-search-forward "^\\\\setfilename") (beginning-of-line) (let ((end (point))) (goto-char (point-min)) (if (re-search-forward "^\\\\alwaysrefill" end t) (setq latexinfo-always-refill t) (setq latexinfo-always-refill nil)) (delete-region (point-min) end)) ;; Remove \end{document} at end of file, if it is there. (goto-char (point-max)) (if (search-backward "\\end{document}" nil t) (delete-region (point) (point-max)) (error "Missing \\end{document}")) ;; Make sure buffer ends in a newline. (or (= (preceding-char) ?\n) (insert "\n")) ;; Scan the whole buffer, converting to Info format. (goto-char (point-min)) (latexinfo-format-scan-noverbatim) ;; Return data for indices. (goto-char (point-min)) (list outfile latexinfo-cindex latexinfo-vindex latexinfo-findex latexinfo-pindex latexinfo-tindex latexinfo-kindex latexinfo-refindex) )) (defvar latexinfo-region-buffer-name "*Info Region*" "*Name of the temporary buffer used by \\[latexinfo-format-region].") (defun latexinfo-format-region (region-beginning region-ending) "Convert the the current region of the Latexinfo file to Info format. This lets you see what that part of the file will look like in Info. The command is bound to \\[latexinfo-format-region]. The text that is converted to Info is stored in a temporary buffer." (interactive "r") (message "Converting region to Info format...") (let (latexinfo-command-start latexinfo-command-end latexinfo-command-name latexinfo-vindex latexinfo-findex latexinfo-cindex latexinfo-pindex latexinfo-tindex latexinfo-kindex latexinfo-refindex latexinfo-stack latexinfo-format-filename latexinfo-example-start latexinfo-last-node-pos latexinfo-last-node latexinfo-node-names (latexinfo-table-number 0) (latexinfo-footnote-number 0) (fill-column (1- fill-column)) (input-buffer (current-buffer)) (input-directory default-directory) filename-beginning filename-ending) ;; Find a buffer to use. (switch-to-buffer (get-buffer-create latexinfo-region-buffer-name)) ;; Insert the region into the buffer. (erase-buffer) (save-excursion (set-buffer input-buffer) (save-excursion (save-restriction (widen) (goto-char (point-min)) ;; Initialize the buffer with the filename ;; or else explain that a filename is needed. (or (re-search-forward "^\\\\setfilename" (save-excursion (forward-line 100) (point)) t) (error "The latexinfo file needs a line saying: \\setfilename ")) (beginning-of-line) (setq filename-beginning (point)) (forward-line 1) (setq filename-ending (point))))) ;; Insert the \\setfilename line into the buffer. (insert-buffer-substring input-buffer (min filename-beginning region-beginning) filename-ending) ;; Insert the region into the buffer. (insert-buffer-substring input-buffer (max region-beginning filename-ending) region-ending) (latexinfo-mode) ;; Install a syntax table useful for scanning command operands. (set-syntax-table latexinfo-format-syntax-table) ;; If the region includes the effective end of the data, ;; discard everything after that. (goto-char (point-max)) (if (search-backward "\\end{document}" nil t) (delete-region (point) (point-max))) ;; Make sure buffer ends in a newline. (or (= (preceding-char) ?\n) (insert "\n")) (goto-char (point-max)) ;; Now convert for real. (goto-char (point-min)) (latexinfo-format-scan-noverbatim) (goto-char (point-min))) ) ;; Only look at the beginning of the line to avoid \c \input{foo} (defvar latexinfo-special-regexp "^[ \t]*\\\\\\(begin{verbatim}\\|begin{smallverbatim}\\|verb\\|input{\\)") (defun latexinfo-format-scan-noverbatim () (if (re-search-forward latexinfo-special-regexp nil t) (let ((start (point-min)) (end nil) str) (goto-char start) (while (re-search-forward latexinfo-special-regexp nil t) (setq str (buffer-substring (match-beginning 0) (match-end 0))) ;; Handle LaTeX \input{filename} commands by inserting them now. ;; Only look at the beginning of the line to avoid \c \input{foo} ;; Protect the verbatim areas from global substitutions. (cond ((string-equal str "\\input{") (latexinfo-insert-input-files) ) ((string-equal str "\\begin{verbatim}") (setq end (point)) (latexinfo-do-global-substitutions start end) (re-search-forward "\\\\end{verbatim}" nil nil) (setq start (point)) ) ((string-equal str "\\begin{smallverbatim}") (setq end (point)) (latexinfo-do-global-substitutions start end) (re-search-forward "\\\\end{smallverbatim}" nil nil) (setq start (point)) ) ((string-equal str "\\verb") (setq end (point)) (latexinfo-do-global-substitutions start end) (setq str (buffer-substring (point) (1+ (point)))) (forward-char 1) (search-forward str nil nil) (forward-char 1) (setq start (point)) ) ) ) (if end (latexinfo-do-global-substitutions start (point-max))) ) (latexinfo-do-global-substitutions (point-min) (point-max)) ) (latexinfo-format-scan)) (defun latexinfo-insert-input-files () (save-excursion ;; (skip-chars-forward " \t{") (let ((file-name (buffer-substring (point) (progn (skip-chars-forward "^ }\n") (point)))) (dirlist latexinfo-texinputs) (the-file nil)) (while (and (not the-file) dirlist) (let ((dir (car dirlist))) (setq the-file (cond ((file-readable-p (expand-file-name file-name dir)) (expand-file-name file-name dir)) ((file-readable-p (expand-file-name (concat file-name ".tex") dir)) (expand-file-name (concat file-name ".tex") dir)) (t nil) )) (setq dirlist (cdr dirlist)))) (setq file-name the-file) (beginning-of-line 1) (if (file-readable-p file-name) (progn (delete-region (point) (progn (forward-line 1) (point))) (message "Inserting file %s..." file-name) (sit-for 1) (insert-file file-name) (message "Inserting file %s...done" file-name)) (error "I can't find the file %s" file-name)) ) ) ) (defun latexinfo-do-global-substitutions (min max) (save-excursion (narrow-to-region min max) (goto-char (point-min)) (let ((start nil)) (while (re-search-forward "^\\\\begin{ignore}" nil t) (beginning-of-line 1) (setq start (point)) (re-search-forward "^\\\\end{ignore}" nil) (forward-line 1) (delete-region start (point)))) ;; LaTeX sometimes uses \\ to force a new-line (goto-char (point-min)) (quietly-replace-regexp "\\\\\\\\$" "") ;; Convert left and right quotes to typewriter font quotes. (goto-char (point-min)) (while (search-forward "``" nil t) (replace-match "\"")) (goto-char (point-min)) (while (search-forward "''" nil t) (replace-match "\"")) (if latexinfo-always-refill (latexinfo-do-refill) ) (widen) ) ) (defun latexinfo-do-refill () (let ((start (point-min)) (end nil)) (goto-char start) (while (re-search-forward "^\\\\begin{menu}" nil t) (narrow-to-region start (point)) ;; Would a regexp be too slow? (goto-char (point-min)) (quietly-replace-string ".\n\n" ".\\refill\n\n" nil) (goto-char (point-min)) (quietly-replace-string ":\n\n" ":\\refill\n\n" nil) (goto-char (point-min)) (quietly-replace-string ".\n\\end" ".\\refill\n\\end" nil) (narrow-to-region min max) (re-search-forward "\\\\end{menu}" nil nil) (setq start (point)) ) ) ) (defun latexinfo-format-scan () ;; Scan for \\-commands. (set-syntax-table latexinfo-format-syntax-table) (goto-char (point-min)) (let ((foochar nil)) (while (search-forward "\\" nil t) ;;; EMACS BUG (looking-at "[*{}^'` \t---.:%\"\\\\]") TRUE for & ;; Handle a few special \-followed-by-one-char commands. (setq foochar (following-char)) (cond ((memq foochar '(?* ?\\ ?- ?:)) ;; \* has no effect, since we are not filling. ;; \" can't be reproduced on ascii terminals (delete-region (1- (point)) (1+ (point)))) ((memq foochar '(?^ ?' ?` ?\")) (latexinfo-parse-accent)) ((memq foochar '(?* ?\{ ?} ?^ ?\ ?\t ?\. ?: ?% ?\\)) ;; The other characters are simply quoted. Delete the \. (delete-char -1) (forward-char 1)) (t ;; \ is followed by a command-word; find the end of the word. (setq latexinfo-command-start (1- (point))) ;; (if (= (char-syntax (following-char)) ?w) . (forward-char 1)) (forward-word 1) (setq latexinfo-command-end (point)) ;; Call the handler for this command. (setq latexinfo-command-name (intern (buffer-substring (1+ latexinfo-command-start) latexinfo-command-end))) (let ((cmd (get latexinfo-command-name 'latexinfo-format))) (if cmd (funcall cmd) (latexinfo-unsupported)))) ) ) (cond (latexinfo-stack (goto-char (nth 2 (car latexinfo-stack))) (error "Unterminated \\begin{%s}" (car (car latexinfo-stack))))) ) ) (defun latexinfo-parse-accent () (latexinfo-delete-whitespace) (cond ((looking-at ".{") (delete-region (1- (point)) (+ 2 (point))) (skip-chars-forward "^}") (delete-char 1) ; } ) (t ; this should not happen (delete-region (1- (point)) (1+ (point))) ; \c ) ) ) (put 'begin 'latexinfo-format 'latexinfo-format-begin) (defun latexinfo-format-begin () (latexinfo-format-begin-end 'latexinfo-format)) (put 'end 'latexinfo-format 'latexinfo-format-end) (defun latexinfo-format-end () (latexinfo-format-begin-end 'latexinfo-end)) (defun latexinfo-format-begin-end (prop) (setq latexinfo-command-name (intern (latexinfo-parse-line-arg))) (setq cmd (get latexinfo-command-name prop)) (if cmd (funcall cmd) (latexinfo-unsupported))) (defvar latexinfo-format-syntax-table-a nil) (progn (setq latexinfo-format-syntax-table-a (copy-syntax-table latexinfo-format-syntax-table)) (modify-syntax-entry ?\[ "." latexinfo-format-syntax-table-a) (modify-syntax-entry ?\] "." latexinfo-format-syntax-table-a) ) ;;Fundamental change (defun safe-forward-list (arg) (cond ((string-equal "}" arg) (set-syntax-table latexinfo-format-syntax-table-a) (forward-sexp 1) (set-syntax-table latexinfo-format-syntax-table) ) ((string-equal "]" arg) (forward-list 1)) (t (forward-list 1)) ) ) (defun latexinfo-parse-line-arg () "Returns the command that takes up the rest of the line." (goto-char latexinfo-command-end) (let ((start (point))) (cond ((looking-at " ") (skip-chars-forward " ") (setq start (point)) (end-of-line) (skip-chars-backward " ") (delete-region (point) (progn (end-of-line) (point))) (setq latexinfo-command-end (1+ (point)))) ((looking-at "{") (setq start (1+ (point))) (safe-forward-list "}") (setq latexinfo-command-end (point)) (forward-char -1)) ((looking-at "\\[") (setq start (1+ (point))) (safe-forward-list "]") (setq latexinfo-command-end (point)) (forward-char -1)) (t (error "Invalid latexinfo command arg format"))) (prog1 (buffer-substring start (point)) (if (eolp) (forward-char 1))))) (defun latexinfo-parse-expanded-arg () (goto-char latexinfo-command-end) (let ((start (point)) marker) (cond ((looking-at " ") (skip-chars-forward " ") (setq start (point)) (end-of-line) (setq latexinfo-command-end (1+ (point)))) ((or (looking-at "{") (looking-at "\\[")) (setq start (1+ (point))) (forward-list 1) (setq latexinfo-command-end (point)) (forward-char -1)) (t (error "Invalid latexinfo command arg format"))) (setq marker (move-marker (make-marker) latexinfo-command-end)) (latexinfo-format-expand-region start (point)) (setq latexinfo-command-end (marker-position marker)) (move-marker marker nil) (prog1 (buffer-substring start (point)) (if (eolp) (forward-char 1))))) (defun latexinfo-parse-arg-discard () (prog1 (latexinfo-parse-line-arg) (latexinfo-discard-command))) (defun latexinfo-discard-command () ;;LaTeX gobbles the next whitespace. Should Info? (delete-region latexinfo-command-start latexinfo-command-end)) (defun latexinfo-parse-noarg () (goto-char latexinfo-command-end) (cond ((looking-at "{}") (delete-char 2)) ;; TeX gobbles the next whitespace. ((eolp) (delete-char 1)) ((looking-at "[ \t]") (setq latexinfo-command-end (save-excursion (skip-chars-forward " \t") (point)))) ) (delete-region latexinfo-command-start latexinfo-command-end) ) ;; New parsing functions (defun latexinfo-parse-required-argument () ;; TeX gobbles the next whitespace. (goto-char latexinfo-command-end) (latexinfo-delete-whitespace) (cond ((looking-at "{") (setq latexinfo-command-end (save-excursion (forward-sexp 1) (point)))) (t (error "latexinfo-parse-required-argument: no argument provided")) ) (prog1 (buffer-substring (1+ (point)) (1- latexinfo-command-end)) (latexinfo-delete-command )) ) (defun latexinfo-delete-whitespace () (if (looking-at "[ \t\n]") (delete-region (point) (save-excursion (skip-chars-forward " \t\n") (point))))) (defun latexinfo-insert-required-argument () (save-excursion (insert (latexinfo-parse-required-argument)))) (defun latexinfo-delete-command () (delete-region latexinfo-command-start latexinfo-command-end)) (defun latexinfo-format-expand-region (start end) (save-restriction (narrow-to-region start end) (let (latexinfo-command-start latexinfo-command-end latexinfo-command-name latexinfo-stack) (latexinfo-format-scan)) (goto-char (point-max)))) (defun latexinfo-format-parse-line-args () (let ((start (1- (point))) next beg end args) (skip-chars-forward " ") (while (not (eolp)) (setq beg (point)) (re-search-forward "[\n,]") (setq next (point)) (if (bolp) (setq next (1- next))) (forward-char -1) (skip-chars-backward " ") (setq end (point)) (setq args (cons (if (> end beg) (buffer-substring beg end)) args)) (goto-char next) (skip-chars-forward " ")) (if (eolp) (forward-char 1)) (setq latexinfo-command-end (point)) (nreverse args))) (defun latexinfo-format-parse-args () (let ((start (1- (point))) next beg end args) (search-forward "{") (while (/= (preceding-char) ?\}) (skip-chars-forward " \t\n") (setq beg (point)) (re-search-forward "[},]") (setq next (point)) (forward-char -1) (skip-chars-backward " \t\n") (setq end (point)) (cond ((< beg end) (goto-char beg) (while (search-forward "\n" end t) (replace-match " ")))) (setq args (cons (if (> end beg) (buffer-substring beg end)) args)) (goto-char next)) (if (eolp) (forward-char 1)) (setq latexinfo-command-end (point)) (nreverse args))) (put 'document 'latexinfo-format 'latexinfo-discard-line) (put 'document 'latexinfo-end 'latexinfo-discard-line) (put 'setfilename 'latexinfo-format 'latexinfo-format-setfilename) (defun latexinfo-format-setfilename () (let ((arg (latexinfo-parse-arg-discard))) (setq latexinfo-format-filename (file-name-nondirectory (expand-file-name arg))) (insert "Info file: " latexinfo-format-filename ", -*-Text-*-\n" "produced by latexinfo-format-buffer\nfrom " (if (buffer-file-name input-buffer) (concat "file: " (file-name-sans-versions (file-name-nondirectory (buffer-file-name input-buffer)))) (concat "buffer " (buffer-name input-buffer))) "\n\n"))) (put 'node 'latexinfo-format 'latexinfo-format-node) (defun latexinfo-format-node () (let* ((args (latexinfo-format-parse-line-args)) (name (nth 0 args)) (next (nth 1 args)) (prev (nth 2 args)) (up (nth 3 args))) (latexinfo-discard-command) (setq latexinfo-last-node name) (let ((tem (downcase name))) (if (assoc tem latexinfo-node-names) (error "Duplicate node name: %s" name) (setq latexinfo-node-names (cons tem latexinfo-node-names)))) (or (bolp) (insert ?\n)) (insert "\^_\nFile: " latexinfo-format-filename " Node: " name) (if prev (insert ", Prev: " prev)) (if up (insert ", Up: " up)) (if next (insert ", Next: " next)) (insert ?\n) (setq latexinfo-last-node-pos (point)) )) (put 'menu 'latexinfo-format 'latexinfo-format-menu) (defun latexinfo-format-menu () (latexinfo-discard-line) (insert "* Menu:\n\n")) (put 'menu 'latexinfo-end 'latexinfo-discard-command) (defun latexinfo-discard-line () (goto-char latexinfo-command-end) (skip-chars-forward " \t") (or (eolp) (error "Extraneous text at end of command line.")) (delete-region latexinfo-command-start (progn (forward-line 1) (point)))) (defun latexinfo-discard-to-eoline () (goto-char latexinfo-command-end) (skip-chars-forward " \t") (or (eolp) (error "Extraneous text at end of command line.")) (delete-region latexinfo-command-start (point))) ; \xref {NODE, FNAME, NAME, FILE, DOCUMENT} ; -> *Note FNAME: (FILE)NODE ; If FILE is missing, ; *Note FNAME: NODE ; If FNAME is empty and NAME is present ; *Note NAME: Node ; If both NAME and FNAME are missing ; *Note NODE:: ; latexinfo ignores the DOCUMENT argument. ; -> See section [NAME, else NODE], page ; If FILE is specified, (FILE)NODE is used for xrefs. ; If fifth argument DOCUMENT is specified, produces ; See section [NAME, else NODE], page ; of DOCUMENT ; \nxref is a reference that does not put `See' or `see' in ; the hardcopy and is the same as \xref in Info (put 'nxref 'latexinfo-format 'latexinfo-format-xref) (put 'xref 'latexinfo-format 'latexinfo-format-xref) (defun latexinfo-format-xref () (let ((args (latexinfo-format-parse-args))) (latexinfo-discard-command) (insert "*Note ") (let ((fname (or (nth 1 args) (nth 2 args)))) (if (null (or fname (nth 3 args))) (insert (car args) "::") (insert (or fname (car args)) ": ") (if (nth 3 args) (insert "(" (nth 3 args) ")")) (insert (car args)))))) (put 'pxref 'latexinfo-format 'latexinfo-format-pxref) (defun latexinfo-format-pxref () (latexinfo-format-xref) (or (save-excursion (forward-char -2) (looking-at "::")) (insert "."))) ;\inforef{NODE, FNAME, FILE} ;Like \xref{NODE, FNAME,,FILE} in latexinfo. ;In LaTeX, generates "See Info file FILE, node NODE" (put 'inforef 'latexinfo-format 'latexinfo-format-inforef) (defun latexinfo-format-inforef () (let ((args (latexinfo-format-parse-args))) (latexinfo-discard-command) (if (nth 1 args) (insert "*Note " (nth 1 args) ": (" (nth 2 args) ")" (car args)) (insert "*Note " "(" (nth 2 args) ")" (car args) "::")))) (put 'appendix 'latexinfo-format 'latexinfo-parse-noarg) (put 'onecolumn 'latexinfo-format 'latexinfo-parse-noarg) (put 'twocolumn 'latexinfo-format 'latexinfo-parse-noarg) ;;(put 'threecolumn 'latexinfo-format 'latexinfo-parse-noarg) (put 'chapter 'latexinfo-format 'latexinfo-format-chapter) (put 'chapter* 'latexinfo-format 'latexinfo-format-chapter) (put 'unnumbered 'latexinfo-format 'latexinfo-format-chapter) (defun latexinfo-format-chapter () (latexinfo-format-chapter-1 ?*)) (put 'section 'latexinfo-format 'latexinfo-format-section) (put 'section* 'latexinfo-format 'latexinfo-format-section) (put 'unnumberedsec 'latexinfo-format 'latexinfo-format-section) (defun latexinfo-format-section () (latexinfo-format-chapter-1 ?=)) (put 'subsection 'latexinfo-format 'latexinfo-format-subsection) (put 'subsection* 'latexinfo-format 'latexinfo-format-subsection) (put 'unnumberedsubsec 'latexinfo-format 'latexinfo-format-subsection) (defun latexinfo-format-subsection () (latexinfo-format-chapter-1 ?-)) (put 'subsubsection 'latexinfo-format 'latexinfo-format-subsubsection) (put 'subsubsection* 'latexinfo-format 'latexinfo-format-subsubsection) (put 'unnumberedsubsubsec 'latexinfo-format 'latexinfo-format-subsubsection) (defun latexinfo-format-subsubsection () (latexinfo-format-chapter-1 ?.)) (defun latexinfo-format-chapter-1 (belowchar) (let ((arg (latexinfo-parse-arg-discard))) (message "Formatting: %s ... " arg) ; So we can see where we are. (insert ?\n arg ?\n "\\SectionPAD " belowchar ?\n) (if (not (looking-at "\n")) (insert "\n")) (goto-char latexinfo-command-start))) (put 'SectionPAD 'latexinfo-format 'latexinfo-format-sectionpad) (defun latexinfo-format-sectionpad () (let ((str (latexinfo-parse-arg-discard))) (forward-char -1) (let ((column (current-column))) (forward-char 1) (while (> column 0) (insert str) (setq column (1- column)))) (insert ?\n) (if (not (looking-at "\n")) (insert "\n")) )) (put 'paragraph 'latexinfo-format 'latexinfo-format-var) (put 'subparagraph 'latexinfo-format 'latexinfo-format-noop) (put 'paragraph* 'latexinfo-format 'latexinfo-format-var) (put 'subparagraph* 'latexinfo-format 'latexinfo-format-noop) (put '\. 'latexinfo-format 'latexinfo-format-\.) (defun latexinfo-format-\. () (latexinfo-discard-command) (insert ".")) (put '\\ 'latexinfo-format 'latexinfo-format-\\) (defun latexinfo-format-\\ () (latexinfo-discard-command) (insert "\n")) (put '\: 'latexinfo-format 'latexinfo-format-\:) (defun latexinfo-format-\: () (latexinfo-discard-command)) (put '_ 'latexinfo-format 'latexinfo-format-_) (defun latexinfo-format-_ () (latexinfo-parse-noarg) (insert "_")) (put '$ 'latexinfo-format 'latexinfo-format-$) (defun latexinfo-format-$ () (latexinfo-parse-noarg) (insert "$")) (put '@ 'latexinfo-format 'latexinfo-format-@) (defun latexinfo-format-@ () (latexinfo-parse-noarg) (insert "@")) (put '~ 'latexinfo-format 'latexinfo-format-~) (defun latexinfo-format-~ () (latexinfo-parse-noarg) (insert "~")) (put '^ 'latexinfo-format 'latexinfo-format-^) (defun latexinfo-format-^ () (latexinfo-parse-noarg) (insert "^")) (put '/ 'latexinfo-format 'latexinfo-format-/) (defun latexinfo-format-/ () (latexinfo-parse-noarg)) (put '\ 'latexinfo-format 'latexinfo-format-space) (defun latexinfo-format-space () (latexinfo-parse-noarg) (insert " ")) ;; Use \tie when you need one. (put 'tie 'latexinfo-format 'latexinfo-format-tie) (defun latexinfo-format-tie () (latexinfo-parse-noarg) (insert " ")) (put 'sp 'latexinfo-format 'latexinfo-format-sp) (defun latexinfo-format-sp () (let ((arg (read (latexinfo-parse-expanded-arg)))) (latexinfo-discard-command) ;; Delete eol if the space command is the only thing on a line (if (and (eolp) (bolp) (not (eobp))) (delete-char 1)) (while (> arg 0) (insert "\n") (setq arg (1- arg))))) ;;; \footnote and \footnotestyle ; In Latexinfo, footnotes are created with the `\footnote' command. ; This command is followed immediately by a left brace, then by the text of ; the footnote, and then by a terminating right brace. The ; template for a footnote is: ; ; \footnote{TEXT} ; ; Info has two footnote styles: ; ; * In the End of node style, all the footnotes for a single node ; are placed at the end of that node. The footnotes are ; separated from the rest of the node by a line of dashes with ; the word `Footnotes' within it. ; ; * In the Separate node style, all the footnotes for a single node ; are placed in an automatically constructed node of their own. ; Footnote style is specified by the \footnotestyle command, either ; \footnotestyle{separate} ; or ; \footnotestyle{end} ; ; The default is separate (defvar latexinfo-footnote-style "separate" "Footnote style, either separate or end.") (put 'footnotestyle 'latexinfo-format 'latexinfo-footnotestyle) (defun latexinfo-footnotestyle () "Specify whether footnotes are at end of node or in separate nodes. Argument is either end or separate." (setq latexinfo-footnote-style (latexinfo-parse-arg-discard))) (defvar latexinfo-footnote-number) (put 'footnote 'latexinfo-format 'latexinfo-format-footnote) (defun latexinfo-format-footnote () "Format a footnote in either end of node or separate node style. The latexinfo-footnote-style variable controls which style is used." (setq latexinfo-footnote-number (1+ latexinfo-footnote-number)) (cond ((string= latexinfo-footnote-style "end") (latexinfo-format-end-node)) ((string= latexinfo-footnote-style "separate") (latexinfo-format-separate-node)))) (defun latexinfo-format-separate-node () "Format footnote in Separate node style, with notes in own node. The node is constructed automatically." (let* (start (arg (latexinfo-parse-line-arg)) (node-name-beginning (save-excursion (re-search-backward "^File: \\w+\\(\\w\\|\\s_\\|\\.\\|,\\)*[ \t]+Node:") (match-end 0))) (node-name (save-excursion (buffer-substring (progn (goto-char node-name-beginning) ; skip over node command (skip-chars-forward " \t") ; and over spaces (point)) (if (search-forward "," (save-excursion (end-of-line) (point)) t) ; bound search (1- (point)) (end-of-line) (point)))))) (latexinfo-discard-command) ; remove or insert whitespace, as needed (delete-region (save-excursion (skip-chars-backward " \t\n") (point)) (point)) (insert (format " (%d) (*Note %s-Footnotes::)" latexinfo-footnote-number node-name)) (fill-paragraph nil) (save-excursion (if (re-search-forward "^\\\\node" nil 'move) (forward-line -1)) ;; two cases: for the first footnote, we must insert a node header; ;; for the second and subsequent footnotes, we need only insert ;; the text of the footnote. (if (save-excursion (re-search-backward (concat node-name "-Footnotes, Up: ") node-name-beginning t)) (progn ; already at least one footnote (setq start (point)) (insert (format "\n(%d) %s\n" latexinfo-footnote-number arg)) (fill-region start (point))) ;; else not yet a footnote (insert "\n\^_\nFile: " latexinfo-format-filename " Node: " node-name "-Footnotes, Up: " node-name "\n") (setq start (point)) (insert (format "\n(%d) %s\n" latexinfo-footnote-number arg)) (fill-region start (point)))))) (defun latexinfo-format-end-node () "Format footnote in the End of node style, with notes at end of node." (let (start (arg (latexinfo-parse-line-arg))) (latexinfo-discard-command) ; remove or insert whitespace, as needed (delete-region (save-excursion (skip-chars-backward " \t\n") (point)) (point)) (insert (format " (%d) " latexinfo-footnote-number)) (fill-paragraph nil) (save-excursion (if (search-forward "\n--------- Footnotes ---------\n" nil t) (progn ; already have footnote, put new one before end of node (if (re-search-forward "^\\\\node" nil 'move) (forward-line -1)) (setq start (point)) (insert (format "\n(%d) %s\n" latexinfo-footnote-number arg)) (fill-region start (point))) ;; else no prior footnote (if (re-search-forward "^\\\\node" nil 'move) (forward-line -1)) (insert "\n--------- Footnotes ---------\n") (setq start (point)) (insert (format "\n(%d) %s\n" latexinfo-footnote-number arg)))))) ;; \begin{itemize} pushes (itemize "COMMANDS" STARTPOS) on latexinfo-stack. ;; \begin{enumerate} pushes (enumerate 0 STARTPOS). ;; \item dispatches to the latexinfo-item prop of the first elt of the list. ;; For itemize, this puts in and rescans the COMMANDS. ;; For enumerate, this increments the number and puts it in. ;; In either case, it puts a Backspace at the front of the line ;; which marks it not to be indented later. ;; All other lines get indented by 5 when the \end is reached. (defvar latexinfo-stack-depth 0 "Count of number of unpopped latexinfo-push-stack calls. Used by \\refill indenting command to avoid indenting within lists, etc.") (defun latexinfo-push-stack (check arg) (setq latexinfo-stack-depth (1+ latexinfo-stack-depth)) (setq latexinfo-stack (cons (list check arg latexinfo-command-start) latexinfo-stack))) (defun latexinfo-pop-stack (check) (setq latexinfo-stack-depth (1- latexinfo-stack-depth)) (if (null latexinfo-stack) (error "Unmatched \\end{%s}" check)) (if (not (eq (car (car latexinfo-stack)) check)) (error "\\end{%s} matches \\begin{%s}" check (car (car latexinfo-stack)))) (prog1 (cdr (car latexinfo-stack)) (setq latexinfo-stack (cdr latexinfo-stack)))) (put 'itemize 'latexinfo-format 'latexinfo-itemize) (defun latexinfo-itemize () (latexinfo-push-stack 'itemize "*") (setq fill-column (- fill-column 5)) (latexinfo-discard-line)) (put 'itemize 'latexinfo-end 'latexinfo-end-itemize) (defun latexinfo-end-itemize () (setq fill-column (+ fill-column 5)) (latexinfo-discard-command) (let ((stacktop (latexinfo-pop-stack 'itemize))) (latexinfo-do-itemize (nth 1 stacktop)))) (put 'enumerate 'latexinfo-format 'latexinfo-enumerate) (defun latexinfo-enumerate () (latexinfo-push-stack 'enumerate 0) (setq fill-column (- fill-column 5)) (latexinfo-discard-line)) (put 'enumerate 'latexinfo-end 'latexinfo-end-enumerate) (defun latexinfo-end-enumerate () (setq fill-column (+ fill-column 5)) (latexinfo-discard-command) (let ((stacktop (latexinfo-pop-stack 'enumerate))) (latexinfo-do-itemize (nth 1 stacktop)))) (put 'center 'latexinfo-format 'latexinfo-format-center) (defun latexinfo-format-center () (latexinfo-push-stack 'center 0) (latexinfo-discard-line)) (put 'center 'latexinfo-end 'latexinfo-end-center) (defun latexinfo-end-center () (latexinfo-discard-command) (let ((stacktop (latexinfo-pop-stack 'center))) (latexinfo-do-center (nth 1 stacktop)))) (defun latexinfo-do-center (from) (let ((indent-tabs-mode nil)) (if (not (or (eobp) (bolp))) (forward-line 1)) (while (progn (forward-line -1) (>= (point) from)) (let ((indent-tabs-mode nil)) (center-line))))) (put 'caption 'latexinfo-format 'latexinfo-caption) (defun latexinfo-caption () (insert (format "Table %d : %s" latexinfo-table-number (latexinfo-parse-arg-discard))) (center-line) (goto-char latexinfo-command-start)) ;;; Tables and figures ;;; & is a special character for the tabular environment. ;;; Use \& if you want to insert an & in a table. (put '& 'latexinfo-format 'latexinfo-format-&) (defun latexinfo-format-& () (if (not (assoc 'tabular latexinfo-stack)) ; if we're not inside tabular (progn (latexinfo-parse-noarg) (insert "&")))) ;; Math tabular environments are ignored. (put 'displaymath 'latexinfo-format 'latexinfo-format-displaymath) (put 'displaymath 'latexinfo-end 'latexinfo-discard-command) (defun latexinfo-format-displaymath () (delete-region latexinfo-command-start (progn (re-search-forward "\\\\end[ {]displaymath[ }\n]") (point)))) (put 'equation 'latexinfo-format 'latexinfo-format-equation) (put 'equation 'latexinfo-end 'latexinfo-discard-command) (defun latexinfo-format-equation () (delete-region latexinfo-command-start (progn (re-search-forward "\\\\end[ {]equation[ }\n]") (point)))) (put 'eqnarray 'latexinfo-format 'latexinfo-format-eqnarray) (put 'eqnarray 'latexinfo-end 'latexinfo-discard-command) (defun latexinfo-format-eqnarray () (delete-region latexinfo-command-start (progn (re-search-forward "\\\\end[ {]eqnarray[ }\n]") (point)))) (put 'array 'latexinfo-format 'latexinfo-format-array) (put 'array 'latexinfo-end 'latexinfo-discard-command) (defun latexinfo-format-array () (delete-region latexinfo-command-start (progn (re-search-forward "\\\\end[ {]array[ }\n]") (point)))) ;;; The tabular environment (put 'tabular 'latexinfo-format 'latexinfo-format-tabular) (put 'tabular 'latexinfo-end 'latexinfo-end-tabular) (defun latexinfo-format-tabular () (latexinfo-push-stack 'tabular nil) (latexinfo-discard-line-with-args)) (defun latexinfo-end-tabular () (latexinfo-discard-command) (let ((stacktop (latexinfo-pop-stack 'tabular))) (latexinfo-do-tabular (nth 1 stacktop)))) (put 'hline 'latexinfo-format 'latexinfo-format-hline) (put 'rule 'latexinfo-format 'latexinfo-format-hline) (defun latexinfo-format-hline () (let ((dashes (make-string fill-column ?-))) (latexinfo-discard-line-with-args) (if (not (bolp)) (insert "\n")) (insert dashes "\n"))) (defun latexinfo-do-tabular (from) (let ((end (point))) (save-excursion (narrow-to-region from end) (goto-char from) (while (search-forward "&" end t) (if (save-excursion (forward-char -2) (not (looking-at "\\\\"))) (progn (delete-char -1) (insert " ")) (progn (delete-char -2) (insert "&")))) (goto-char from) (quietly-replace-regexp "\\\\\\\\$" "") (untabify from end) ;; Give it some boundaries to protect from centering ;; (goto-char from) ;; (replace-regexp "^" "| ") (widen) ))) (put 'table 'latexinfo-format 'latexinfo-format-table) (put 'table* 'latexinfo-format 'latexinfo-format-table) (put 'table 'latexinfo-end 'latexinfo-discard-command) (defun latexinfo-format-table () (latexinfo-discard-line-with-args) (setq latexinfo-table-number (1+ latexinfo-table-number))) ;; Figures are ignored for now (put 'figure 'latexinfo-format 'latexinfo-format-figure) (put 'figure* 'latexinfo-format 'latexinfo-format-figure) (put 'figure 'latexinfo-end 'latexinfo-discard-command) (defun latexinfo-format-figure () (delete-region latexinfo-command-start (progn (re-search-forward "\\\\end[ {]figure[ }]*\n") (point)))) (put 'description 'latexinfo-format 'latexinfo-description) (defun latexinfo-description () (latexinfo-push-stack 'description "") (setq fill-column (- fill-column 5)) (latexinfo-discard-line)) (put 'description 'latexinfo-end 'latexinfo-end-description) (defun latexinfo-end-description () (setq fill-column (+ fill-column 5)) (latexinfo-discard-command) (let ((stacktop (latexinfo-pop-stack 'description))) (latexinfo-do-itemize (nth 1 stacktop)))) (put 'description 'latexinfo-item 'latexinfo-description-item) (defun latexinfo-description-item () (let ((arg (latexinfo-parse-arg-discard))) (insert ?\b arg "\n \n")) (forward-line -2)) ;; At the \end, indent all the lines within the construct ;; except those marked with backspace. FROM says where ;; construct started. (defun latexinfo-do-itemize (from) (save-excursion (while (progn (forward-line -1) (>= (point) from)) (if (= (following-char) ?\b) (save-excursion (delete-char 1) (end-of-line) (delete-char 6)) (save-excursion ;; not delete trailing whitespace (and nil (if (looking-at "[ \t]") (delete-region (point) (progn (skip-chars-forward " \t") (point))))) (insert " ")))))) (put 'item 'latexinfo-format 'latexinfo-item) (defun latexinfo-item () (funcall (get (car (car latexinfo-stack)) 'latexinfo-item))) (put 'itemize 'latexinfo-item 'latexinfo-itemize-item) (defun latexinfo-itemize-item () (latexinfo-parse-noarg) (insert "\b " (nth 1 (car latexinfo-stack)) " \n") (forward-line -1)) (put 'enumerate 'latexinfo-item 'latexinfo-enumerate-item) (defun latexinfo-enumerate-item () (latexinfo-parse-noarg) (let ((next (1+ (car (cdr (car latexinfo-stack)))))) (setcar (cdr (car latexinfo-stack)) next) (insert ?\b (format "%3d. " next) ?\n)) (forward-line -1)) (put 'ifinfo 'latexinfo-format 'latexinfo-discard-line) (put 'ifinfo 'latexinfo-end 'latexinfo-discard-command) (put 'iftex 'latexinfo-format 'latexinfo-format-iftex) (defun latexinfo-format-iftex () (delete-region latexinfo-command-start (progn (re-search-forward "\\\\end[ {]iftex[ }\n]") (point)))) (put 'tex 'latexinfo-format 'latexinfo-format-tex) (defun latexinfo-format-tex () (delete-region latexinfo-command-start (progn (re-search-forward "\\end[ {]tex[ }\n]") (point)))) (put 'ignore 'latexinfo-format 'latexinfo-format-ignore) (defun latexinfo-format-ignore () (delete-region latexinfo-command-start (progn (re-search-forward "\\\\end[ {]ignore[ }\n]") (point)))) (put 'endignore 'latexinfo-format 'latexinfo-discard-line) (put 'VAR 'latexinfo-format 'latexinfo-format-var) (put 'var 'latexinfo-format 'latexinfo-format-var) (defun latexinfo-format-var () (insert (upcase (latexinfo-parse-arg-discard))) (goto-char latexinfo-command-start)) (put 'b 'latexinfo-format 'latexinfo-format-noop) (put 'r 'latexinfo-format 'latexinfo-format-noop) (put 'scap 'latexinfo-format 'latexinfo-format-noop) (put 'n 'latexinfo-format 'latexinfo-format-noop) (put 't 'latexinfo-format 'latexinfo-format-noop) (put 'i 'latexinfo-format 'latexinfo-format-noop) (put 'key 'latexinfo-format 'latexinfo-format-noop) (put 'dmn 'latexinfo-format 'latexinfo-format-noop) (put 'w 'latexinfo-format 'latexinfo-format-noop) (defun latexinfo-format-noop () (insert (latexinfo-parse-arg-discard)) (goto-char latexinfo-command-start)) (put 'CODE 'latexinfo-format 'latexinfo-format-code) (put 'code 'latexinfo-format 'latexinfo-format-code) (put 'samp 'latexinfo-format 'latexinfo-format-code) (put 'file 'latexinfo-format 'latexinfo-format-code) (put 'kbd 'latexinfo-format 'latexinfo-format-code) (defun latexinfo-format-code () (insert "`" (latexinfo-parse-arg-discard) "'") (goto-char latexinfo-command-start)) (put 'emph 'latexinfo-format 'latexinfo-format-emph) (put 'strong 'latexinfo-format 'latexinfo-format-emph) (defun latexinfo-format-emph () (insert "*" (latexinfo-parse-arg-discard) "*") (goto-char latexinfo-command-start)) (put 'defn 'latexinfo-format 'latexinfo-format-defn) (put 'dfn 'latexinfo-format 'latexinfo-format-defn) (defun latexinfo-format-defn () (insert "\"" (latexinfo-parse-arg-discard) "\"") (goto-char latexinfo-command-start)) (put 'bullet 'latexinfo-format 'latexinfo-format-bullet) (defun latexinfo-format-bullet () (latexinfo-parse-noarg) (insert "*")) (put 'smallexample 'latexinfo-format 'latexinfo-format-example) (put 'example 'latexinfo-format 'latexinfo-format-example) (put 'quotation 'latexinfo-format 'latexinfo-format-example) (put 'quote 'latexinfo-format 'latexinfo-format-example) (put 'abstract 'latexinfo-format 'latexinfo-format-example) (put 'display 'latexinfo-format 'latexinfo-format-example) (defun latexinfo-format-example () (latexinfo-push-stack 'example nil) (setq fill-column (- fill-column 5)) (latexinfo-discard-to-eoline)) (put 'smallexample 'latexinfo-end 'latexinfo-end-example) (put 'example 'latexinfo-end 'latexinfo-end-example) (put 'quotation 'latexinfo-end 'latexinfo-end-example) (put 'quote 'latexinfo-end 'latexinfo-end-example) (put 'abstract 'latexinfo-end 'latexinfo-end-example) (put 'display 'latexinfo-end 'latexinfo-end-example) (defun latexinfo-end-example () (setq fill-column (+ fill-column 5)) (latexinfo-discard-command) (let ((stacktop (latexinfo-pop-stack 'example))) (latexinfo-do-itemize (nth 1 stacktop)))) (put 'smalllisp 'latexinfo-format 'latexinfo-format-lisp) (put 'lisp 'latexinfo-format 'latexinfo-format-lisp) (defun latexinfo-format-lisp () (latexinfo-push-stack 'lisp nil) (setq fill-column (- fill-column 5)) (latexinfo-discard-to-eoline)) (put 'smalllisp 'latexinfo-end 'latexinfo-end-lisp) (put 'lisp 'latexinfo-end 'latexinfo-end-lisp) (defun latexinfo-end-lisp () (setq fill-column (+ fill-column 5)) (latexinfo-discard-command) (let ((stacktop (latexinfo-pop-stack 'lisp))) (untabify (nth 1 stacktop) (point)) (latexinfo-do-itemize (nth 1 stacktop)))) (put 'exdent 'latexinfo-format 'latexinfo-format-exdent) (defun latexinfo-format-exdent () (latexinfo-discard-command) (delete-region (point) (progn (skip-chars-forward " ") (point))) (insert ?\b) ;; Cancel out the deletion that latexinfo-do-itemize ;; is going to do at the end of this line. (save-excursion (end-of-line) (insert "\n "))) (put 'smallverbatim 'latexinfo-format 'latexinfo-format-smallverbatim) (put 'smallverbatim 'latexinfo-end 'latexinfo-end-smallverbatim) (defun latexinfo-end-smallverbatim () (error "Nested verbatim environments are not supported")) (put 'verbatim 'latexinfo-format 'latexinfo-format-verbatim) (defun latexinfo-format-verbatim () (latexinfo-discard-line) (untabify (point) (progn (re-search-forward "\\\\end{verbatim}" nil nil) (point))) (beginning-of-line 1) (delete-region (point) (save-excursion (forward-line 1) (point)))) (put 'smallverbatim 'latexinfo-format 'latexinfo-format-smallverbatim) (defun latexinfo-format-smallverbatim () (latexinfo-discard-line) (untabify (point) (progn (re-search-forward "\\\\end{smallverbatim}" nil nil) (point))) (beginning-of-line 1) (delete-region (point) (save-excursion (forward-line 1) (point)))) (put 'verbatimfile 'latexinfo-format 'latexinfo-format-verbatimfile) (defun latexinfo-format-verbatimfile () (let ((from (point))) (forward-char 1) (latexinfo-insert-input-files) (untabify (point) (progn (re-search-forward "\\\\end{verbatim}" nil nil) (point))) (beginning-of-line 1) (delete-region (point) (save-excursion (forward-line 1) (point))))) (put 'smallverbatimfile 'latexinfo-format 'latexinfo-format-smallverbatimfile) (defun latexinfo-format-smallverbatimfile () (let ((from (point))) (forward-char 1) (latexinfo-insert-input-files) (untabify (point) (progn (re-search-forward "\\\\end{smallverbatim}" nil nil) (point))) (beginning-of-line 1) (delete-region (point) (save-excursion (forward-line 1) (point))))) (put 'verbatim 'latexinfo-end 'latexinfo-end-verbatim) (defun latexinfo-end-verbatim () (error "Nested verbatim environments are not supported")) (put 'verb 'latexinfo-format 'latexinfo-format-verb) (defun latexinfo-format-verb () "Handle the LaTeX \\verb command." (delete-region latexinfo-command-start latexinfo-command-end) (let ((the-char (buffer-substring (point) (+ 1 (point))))) (delete-char 1) (skip-chars-forward (concat "^" the-char)) (delete-char 1) ) ) ; The \cartouche command is a noop in Info; in a printed manual, ; it makes a box with rounded corners. (put 'cartouche 'latexinfo-format 'latexinfo-discard-line) (put 'cartouche 'latexinfo-end 'latexinfo-discard-command) ;;; flushleft and format environments ; The flushleft environment command left justifies every line but leaves the ; right end ragged. As far as Info is concerned, \flushleft is a ; `do-nothing' command. ; The \begin{format} command is similar to \begin{example} except that ; it does not indent; this means that in Info, format is similar to flushleft. (put 'format 'latexinfo-format 'latexinfo-format-flushleft) (put 'flushleft 'latexinfo-format 'latexinfo-format-flushleft) (defun latexinfo-format-flushleft () (latexinfo-discard-line)) (put 'format 'latexinfo-end 'latexinfo-end-flushleft) (put 'flushleft 'latexinfo-end 'latexinfo-end-flushleft) (defun latexinfo-end-flushleft () (latexinfo-discard-command)) ;;; \begin{flushright} ; The \begin{flushright} command right justifies every line but leaves the ; left end ragged. Spaces and tabs at the right ends of lines are ; removed so that visible text lines up on the right side. (put 'flushright 'latexinfo-format 'latexinfo-format-flushright) (defun latexinfo-format-flushright () (latexinfo-push-stack 'flushright nil) (latexinfo-discard-line)) (put 'flushright 'latexinfo-end 'latexinfo-end-flushright) (defun latexinfo-end-flushright () (latexinfo-discard-command) (let ((stacktop (latexinfo-pop-stack 'flushright))) (latexinfo-do-flushright (nth 1 stacktop)))) (defun latexinfo-do-flushright (from) (save-excursion (while (progn (forward-line -1) (>= (point) from)) (beginning-of-line) (insert (make-string (- fill-column (save-excursion (end-of-line) (skip-chars-backward " \t") (delete-region (point) (progn (end-of-line) (point))) (current-column))) ? ))))) (put 'beforenoterule 'latexinfo-format 'latexinfo-format-hline) (put 'afternoterule 'latexinfo-format 'latexinfo-format-hline) (put 'betweennoterule 'latexinfo-format 'latexinfo-format-hline) (put 'implementation 'latexinfo-format 'latexinfo-format-note) (put 'rationale 'latexinfo-format 'latexinfo-format-note) (put 'sideremark 'latexinfo-format 'latexinfo-format-note) (put 'note 'latexinfo-format 'latexinfo-format-note) (defun latexinfo-format-note () (latexinfo-push-stack 'example nil) (setq fill-column (- fill-column 5)) (latexinfo-discard-line) ) (put 'implementation 'latexinfo-end 'latexinfo-end-note) (put 'rationale 'latexinfo-end 'latexinfo-end-note) (put 'sideremark 'latexinfo-end 'latexinfo-end-note) (put 'note 'latexinfo-end 'latexinfo-end-note) (defun latexinfo-end-note () (setq fill-column (+ fill-column 5)) (latexinfo-discard-command) (let ((stacktop (latexinfo-pop-stack 'example))) (latexinfo-do-itemize (nth 1 stacktop))) ) ;;; \ctrl, \TeX, \copyright, \minus, \dots (put 'ctrl 'latexinfo-format 'latexinfo-format-ctrl) (defun latexinfo-format-ctrl () (let ((str (latexinfo-parse-arg-discard))) (insert "^" str))) ;; (insert (logand 31 (aref str 0))))) (put 'TeX 'latexinfo-format 'latexinfo-format-TeX) (defun latexinfo-format-TeX () (latexinfo-parse-noarg) (insert "TeX")) (put 'copyright 'latexinfo-format 'latexinfo-format-copyright) (defun latexinfo-format-copyright () (latexinfo-parse-noarg) (insert "(C)")) (put 'minus 'latexinfo-format 'latexinfo-format-minus) (defun latexinfo-format-minus () (latexinfo-parse-noarg) (insert "-")) (put 'DOTS 'latexinfo-format 'latexinfo-format-dots) (put 'dots 'latexinfo-format 'latexinfo-format-dots) (defun latexinfo-format-dots () (latexinfo-parse-noarg) (insert "...")) ;;; Refilling and indenting: \refill, \paragraphindent, \noindent ;;; Indent only those paragraphs that are refilled as a result of an ;;; \refill command. ; * If the value is `asis', do not change the existing indentation at ; the starts of paragraphs. ; * If the value zero, delete any existing indentation. ; * If the value is greater than zero, indent each paragraph by that ; number of spaces. ;;; But do not refill paragraphs with an \refill command that are ;;; preceded by \noindent or are part of a table, list, or deffn. (defvar latexinfo-paragraph-indent "asis" "Number of spaces for \\refill to indent a paragraph; else to leave as is.") (put 'paragraphindent 'latexinfo-format 'latexinfo-paragraphindent) (defun latexinfo-paragraphindent () "Specify the number of spaces for \refill to indent a paragraph. Default is to leave the number of spaces as is." (let ((arg (latexinfo-parse-arg-discard))) (if (string= "asis" arg) (setq latexinfo-paragraph-indent "asis") (setq latexinfo-paragraph-indent (string-to-int arg))))) (put 'refill 'latexinfo-format 'latexinfo-format-refill) (defun latexinfo-format-refill () "Refill paragraph. Also, indent first line as set by \\paragraphindent. Default is to leave paragraph indentation as is." (latexinfo-discard-command) (forward-paragraph -1) (if (looking-at "[ \t\n]*$") (forward-line 1)) ;; Do not indent if an entry in a list, table, or deffn, ;; or if paragraph is preceded by \noindent. ;; Otherwise, indent (cond ;; delete a \\noindent line and do not indent paragraph ((save-excursion (forward-line -1) (looking-at "^\\\\noindent")) (forward-line -1) (delete-region (point) (progn (forward-line 1) (point)))) ;; do nothing if "asis" ((equal latexinfo-paragraph-indent "asis")) ;; do no indenting in list, etc. ((> latexinfo-stack-depth 0)) ;; otherwise delete existing whitespace and indent (t (delete-region (point) (progn (skip-chars-forward " \t") (point))) (insert (make-string latexinfo-paragraph-indent ? )))) (forward-paragraph 1) (forward-line -1) (end-of-line) (fill-paragraph nil)) (put 'noindent 'latexinfo-format 'latexinfo-noindent) (defun latexinfo-noindent () (save-excursion (forward-paragraph 1) (if (search-backward "\\refill" (save-excursion (forward-line -1) (point)) t) () ; leave \noindent command so \refill command knows not to indent ;; else (latexinfo-discard-line)))) ;; Index generation (put 'vindex 'latexinfo-format 'latexinfo-format-vindex) (defun latexinfo-format-vindex () (latexinfo-index 'latexinfo-vindex)) (put 'cindex 'latexinfo-format 'latexinfo-format-cindex) (defun latexinfo-format-cindex () (latexinfo-index 'latexinfo-cindex)) (put 'findex 'latexinfo-format 'latexinfo-format-findex) (defun latexinfo-format-findex () (latexinfo-index 'latexinfo-findex)) (put 'pindex 'latexinfo-format 'latexinfo-format-pindex) (defun latexinfo-format-pindex () (latexinfo-index 'latexinfo-pindex)) (put 'tindex 'latexinfo-format 'latexinfo-format-tindex) (defun latexinfo-format-tindex () (latexinfo-index 'latexinfo-tindex)) (put 'kindex 'latexinfo-format 'latexinfo-format-kindex) (defun latexinfo-format-kindex () (latexinfo-index 'latexinfo-kindex)) (put 'label 'latexinfo-format 'latexinfo-format-refindex) (defun latexinfo-format-refindex () (latexinfo-index 'latexinfo-refindex)) (defun latexinfo-index (indexvar) (let ((arg (latexinfo-parse-expanded-arg))) (latexinfo-discard-command) ;; Delete eol if the index command is the only thing on a line (if (and (eolp) (bolp) (not (eobp))) (delete-char 1)) (set indexvar (cons (list arg latexinfo-last-node ;; Region formatting may not provide last node position. (if latexinfo-last-node-pos (1+ (count-lines latexinfo-last-node-pos (point))) 1)) (symbol-value indexvar))))) (put 'pageref 'latexinfo-format 'latexinfo-format-ref) (put 'ref 'latexinfo-format 'latexinfo-format-ref) (defun latexinfo-format-ref () (latexinfo-format-do-ref (latexinfo-parse-arg-discard) 'latexinfo-refindex)) (defun latexinfo-format-do-ref (arg index) (let ((entry (assoc arg (symbol-value index)))) (if (and entry (cdr entry) (car (cdr entry))) (insert "*Note " (car (cdr entry)) "::") (let ((entry (assoc arg (symbol-value (intern (concat (symbol-name index) "-old")))))) (if (and entry (cdr entry) (car (cdr entry))) (insert "*Note " (car (cdr entry)) "::") (insert "?")))))) (defconst latexinfo-indexvar-alist '(("cp" . latexinfo-cindex) ("fn" . latexinfo-findex) ("vr" . latexinfo-vindex) ("tp" . latexinfo-tindex) ("pg" . latexinfo-pindex) ("ky" . latexinfo-kindex))) (put 'printindex 'latexinfo-format 'latexinfo-format-printindex) (defun latexinfo-format-printindex () (let ((indexelts (symbol-value (cdr (assoc (latexinfo-parse-arg-discard) latexinfo-indexvar-alist)))) opoint) (insert "\n* Menu:\n\n") (setq opoint (point)) (latexinfo-print-index nil indexelts) (if (eq system-type 'vax-vms) (latexinfo-sort-region opoint (point)) (shell-command-on-region opoint (point) "sort -fd" 1)))) (defun latexinfo-print-index (file indexelts) (while indexelts (if (stringp (car (car indexelts))) (insert "* " (car (car indexelts)) ": " (if file (concat "(" file ")") "") (nth 1 (car indexelts)) ".\n") ;; index entries from \include'd file (latexinfo-print-index (nth 1 (car indexelts)) (nth 2 (car indexelts)))) (setq indexelts (cdr indexelts)))) ;;;; Lisp Definitions have been moved out into the elisp style. ;;; \set, \clear, \ifset, \ifclear ;; If a flag is set with \set FLAG, then text between \ifset and \end ;; ifset is formatted normally, but if the flag is is cleared with ;; \clear FLAG, then the text is not formatted; it is ignored. ;; If a flag is cleared with \clear FLAG, then text between \ifclear ;; and \end ifclear is formatted normally, but if the flag is is set with ;; \set FLAG, then the text is not formatted; it is ignored. \ifclear ;; is the opposite of \ifset. (put 'clear 'latexinfo-format 'latexinfo-clear) (defun latexinfo-clear () "Clear the value of the flag." (let ((arg (latexinfo-parse-line-arg))) (if (not (boundp (intern arg))) (error "\\clear flag `%s' is not defined by a \\set command." arg)) (latexinfo-discard-command) (set (intern arg) nil))) (put 'set 'latexinfo-format 'latexinfo-set) (defun latexinfo-set () "Set the value of the flag." (let ((arg (latexinfo-parse-arg-discard))) (make-local-variable (intern arg)) (set (intern arg) t))) (put 'ifset 'latexinfo-end 'latexinfo-discard-command) (put 'ifset 'latexinfo-format 'latexinfo-if-set) (defun latexinfo-if-set () "If set, continue formatting; else do not format region up to \\end{ifset}" (let ((arg (latexinfo-parse-line-arg))) (if (not (boundp (intern arg))) (error "\\ifset flag `%s' is not defined by a \\set command." arg)) (latexinfo-discard-command) (if (symbol-value (intern arg)) ;; (message "%s is true." arg) () ;; (message "%s is false." arg) (delete-region latexinfo-command-start (progn (re-search-forward "\\\\end[ {]ifset[ }\t]*\n") (point)))))) (put 'ifclear 'latexinfo-end 'latexinfo-discard-command) (put 'ifclear 'latexinfo-format 'latexinfo-if-clear) (defun latexinfo-if-clear () "If clear, do not format up to \\end{ifclear}; else continue formatting." (let ((arg (latexinfo-parse-line-arg))) (if (not (boundp (intern arg))) (error "\\ifclear flag `%s' is not defined by a \\set command." arg)) (latexinfo-discard-command) (if (symbol-value (intern arg)) (delete-region latexinfo-command-start (progn (re-search-forward "\\\\end[ {]ifset[ }\t]*\n") (point)))))) ;; process included files (put 'include 'latexinfo-format 'latexinfo-format-include) (defun latexinfo-format-include () (let ((filename (latexinfo-parse-arg-discard)) (default-directory input-directory) subindex) (setq subindex (save-excursion (progn (find-file (cond ((file-readable-p filename) filename) ((file-readable-p (concat filename ".latexinfo")) (concat filename ".latexinfo")) ((file-readable-p (concat filename ".tex")) (concat filename ".tex")) ((file-readable-p filename) filename) (t (error "\\include'd file %s not found" filename)))) (latexinfo-format-buffer-1)))) (latexinfo-subindex 'latexinfo-vindex (car subindex) (nth 1 subindex)) (latexinfo-subindex 'latexinfo-findex (car subindex) (nth 2 subindex)) (latexinfo-subindex 'latexinfo-cindex (car subindex) (nth 3 subindex)) (latexinfo-subindex 'latexinfo-pindex (car subindex) (nth 4 subindex)) (latexinfo-subindex 'latexinfo-tindex (car subindex) (nth 5 subindex)) (latexinfo-subindex 'latexinfo-kindex (car subindex) (nth 6 subindex)))) (defun latexinfo-subindex (indexvar file content) (set indexvar (cons (list 'recurse file content) (symbol-value indexvar)))) ;; Sort an index which is in the current buffer between START and END. ;; Used on VMS, where the `sort' utility is not available. (defun latexinfo-sort-region (start end) (require 'sort) (save-restriction (narrow-to-region start end) (sort-subr nil 'forward-line 'end-of-line 'latexinfo-sort-startkeyfun))) ;; Subroutine for sorting an index. ;; At start of a line, return a string to sort the line under. (defun latexinfo-sort-startkeyfun () (let ((line (buffer-substring (point) (save-excursion (end-of-line) (point))))) ;; Canonicalize whitespace and eliminate funny chars. (while (string-match "[ \t][ \t]+\\|[^a-z0-9 ]+" line) (setq line (concat (substring line 0 (match-beginning 0)) " " (substring line (match-end 0) (length line))))) line)) ;; Some cannot be handled - just ignore them and junk the line (defun latexinfo-unsupported () (message "Unsupported LaTeXinfo command: %s" (buffer-substring latexinfo-command-start latexinfo-command-end)) (latexinfo-parse-noarg) ) (defun batch-latexinfo-format () "Runs latexinfo-format-buffer on the files remaining on the command line. Must be used only with -batch, and kills emacs on completion. Each file will be processed even if an error occurred previously. For example, invoke \"emacs -batch -funcall batch-latexinfo-format $docs/ ~/*.tex\"." (if (not noninteractive) (error "batch-latexinfo-format may only be used -batch.")) (let ((version-control t) (auto-save-default nil) (find-file-run-dired nil) (kept-old-versions 259259) (kept-new-versions 259259)) (let ((error 0) file (files ())) (while command-line-args-left (setq file (expand-file-name (car command-line-args-left))) (cond ((not (file-exists-p file)) (message ">> %s does not exist!" file) (setq error 1 command-line-args-left (cdr command-line-args-left))) ((file-directory-p file) (setq command-line-args-left (nconc (directory-files file) (cdr command-line-args-left)))) (t (setq files (cons file files) command-line-args-left (cdr command-line-args-left))))) (while files (setq file (car files) files (cdr files)) (condition-case err (progn (if buffer-file-name (kill-buffer (current-buffer))) (find-file file) (buffer-flush-undo (current-buffer)) (set-buffer-modified-p nil) (latexinfo-mode) (message "Latexinfo formatting %s..." file) (latexinfo-format-buffer nil) (if (buffer-modified-p) (progn (message "Saving modified %s" (buffer-file-name)) (save-buffer)))) (error (message ">> Error: %s" (prin1-to-string err)) (message ">> point at") (let ((s (buffer-substring (point) (min (+ (point) 100) (point-max)))) (tem 0)) (while (setq tem (string-match "\n+" s tem)) (setq s (concat (substring s 0 (match-beginning 0)) "\n>> " (substring s (match-end 0))) tem (1+ tem))) (message ">> %s" s))) (setq error 1))) (kill-emacs error)))) ;;; LaTeX additions (defun latexinfo-run-documentstyle-hooks () "Foreach \\documentstyle-argument DOCSTYLE, look for DOCSTYLE-fmt.[el,elc] in the current directory or load-path. If DOCSTYLE-fmt-hook is bound, run it." (goto-char (point-min)) (search-forward "\\documentstyle") (if (looking-at "\\[") (let ((begin (1+ (point))) (end (save-excursion (search-forward "]") (point))) (options-list nil)) (if (null latexinfo-formats-directory) (setq latexinfo-formats-directory default-directory)) (while (re-search-forward ",\\|]" end t) (setq options-list (cons (buffer-substring begin (1- (point))) options-list)) (setq begin (point))) (setq options-list (nreverse options-list)) (while options-list (let ((option (car options-list)) (filename nil)) (if (not (memq (intern option) latexinfo-known-document-styles)) (progn (message "Checking formatting option %s" option) ;(sit-for 2) (if (load (concat option "-fmt") t) ; dont report errors (let ((option-symbol (intern (concat option "-fmt-hook")))) (if (fboundp option-symbol) (progn (message "Running %s formatting hooks" option) (sit-for 1) (funcall option-symbol))) (message (concat "Done loading file %s" option)) ; (sit-for 1) ; we want it fast ) (message (concat option "-fmt not found")) ) ) ) (setq options-list (cdr options-list))))))) (put 'BACK 'latexinfo-format 'latexinfo-format-backslash) (put 'back 'latexinfo-format 'latexinfo-format-backslash) (defun latexinfo-format-backslash () "replace \\back by \\" (latexinfo-parse-noarg) (insert "\\")) (put 'same 'latexinfo-format 'latexinfo-discard-command) (put 'same 'latexinfo-end 'latexinfo-discard-command) (put 'cite 'latexinfo-format 'latexinfo-format-cite) (defun latexinfo-format-cite () (if (looking-at "[\\[]") (save-excursion (let ((here (point)) (str nil)) (forward-sexp 1) (setq str (buffer-substring (1+ here) (- (point) 1))) (delete-region here (point)) (if (eolp) (delete-char 1)) (insert "[" (latexinfo-parse-arg-discard) ", " str "]"))) (insert "[" (latexinfo-parse-arg-discard) "]")) (goto-char latexinfo-command-start)) (put 'hfill 'latexinfo-format 'latexinfo-format-hfill) (defun latexinfo-format-hfill () (latexinfo-parse-arg-discard) (insert-char ?\ (- fill-column (save-excursion (end-of-line 1) (current-column))))) (put 'S 'latexinfo-format 'latexinfo-format-S) (defun latexinfo-format-S () (latexinfo-parse-noarg) (insert "Section")) ;;; Some European support ;;; \ss (put 'ss 'latexinfo-format 'latexinfo-format-ss) (defun latexinfo-format-ss () (latexinfo-parse-noarg) (insert "ss")) (put 'LaTeX 'latexinfo-format 'latexinfo-format-LaTeX) (defun latexinfo-format-LaTeX () (latexinfo-parse-noarg) (insert "LaTeX")) (put 'BibTeX 'latexinfo-format 'latexinfo-format-BibTeX) (defun latexinfo-format-BibTeX () (latexinfo-parse-noarg) (insert "BibTeX")) (put 'arrow 'latexinfo-format 'latexinfo-format-arrow) (put 'result 'latexinfo-format 'latexinfo-format-arrow) (defun latexinfo-format-arrow () (latexinfo-parse-noarg) (insert "=> ")) (put 'leq 'latexinfo-format 'latexinfo-format-leq) (defun latexinfo-format-leq () (latexinfo-parse-noarg) (insert "<=")) (put 'geq 'latexinfo-format 'latexinfo-format-geq) (defun latexinfo-format-geq () (latexinfo-parse-noarg) (insert ">=")) (put 'pi 'latexinfo-format 'latexinfo-format-pi) (defun latexinfo-format-pi () (latexinfo-parse-noarg) (insert "pi")) (put 'quad 'latexinfo-format 'latexinfo-format-quad) (defun latexinfo-format-quad () (latexinfo-parse-noarg) (insert " ")) (put 'qquad 'latexinfo-format 'latexinfo-format-qquad) (defun latexinfo-format-qquad () (latexinfo-parse-noarg) (insert " ")) (put 'pm 'latexinfo-format 'latexinfo-format-pm) (defun latexinfo-format-pm () (latexinfo-parse-noarg) (insert "+/-")) ;;; Glyphs: \equiv, \error, etc ;; \equiv to show that two expressions are equivalent ;; \error to show an error message ;; \expansion to show what a macro expands to ;; \point to show the location of point in an example ;; \print to show what an evaluated expression prints ;; \result to indicate the value returned by an expression (put 'equiv 'latexinfo-format 'latexinfo-format-equiv) (defun latexinfo-format-equiv () "Indicate the exact equivalence of two forms; special glyph: ==" (latexinfo-parse-noarg) (insert "==")) (put 'error 'latexinfo-format 'latexinfo-format-error) (defun latexinfo-format-error () "Indicate that the following text is an error message: error-->" (latexinfo-parse-noarg) (insert "error-->")) (put 'expansion 'latexinfo-format 'latexinfo-format-expansion) (defun latexinfo-format-expansion () "Indicate the result of a macro expansion; special glyph: ==>" (latexinfo-parse-noarg) (insert "==>")) (put 'point 'latexinfo-format 'latexinfo-format-point) (defun latexinfo-format-point () "Indicate the position of point; special glyph: -!-" (latexinfo-parse-noarg) (insert "-!-")) (put 'print 'latexinfo-format 'latexinfo-format-print) (defun latexinfo-format-print () "Indicate printed output; special glyph: -|" (latexinfo-parse-noarg) (insert "-|")) (put 'c 'latexinfo-format 'latexinfo-discard-commment-line) (put 'comment 'latexinfo-format 'latexinfo-discard-commment-line) (defun latexinfo-discard-commment-line () "Discards commment lines, but tries to be more TeX like by deleting the following whitespace." (latexinfo-discard-line-with-args) (latexinfo-delete-whitespace) ) ;; Lots of bolio constructs do nothing in latexinfo. (defun latexinfo-discard-line-with-args () (goto-char latexinfo-command-start) (delete-region (point) (progn (forward-line 1) (point)))) (put 'need 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'newindex 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'synindex 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'syncodeindex 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'parindent 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'lispnarrowing 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'itemindent 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'PROTECT 'latexinfo-format 'latexinfo-parse-protected-argument) (put 'protect 'latexinfo-format 'latexinfo-parse-protected-argument) (defun latexinfo-parse-protected-argument () ;; TeX gobbles the next whitespace. (goto-char latexinfo-command-end) (latexinfo-delete-whitespace) (cond ((looking-at "{") (setq latexinfo-command-end (save-excursion (forward-sexp 1) (point)))) ) (insert (prog1 (buffer-substring (1+ (point)) (1- latexinfo-command-end)) (latexinfo-delete-command))) ) (put 'protect 'latexinfo-format 'latexinfo-parse-noarg) (put 'PROTECT 'latexinfo-format 'latexinfo-parse-noarg) ;; LaTeX noops (put 'hsize 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'clearpage 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'newpage 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'includeonly 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'cleardoublepage 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'tableofcontents 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'listoftables 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'listoffigures 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'vspace 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'vspace* 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'markboth 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'markright 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'index 'latexinfo-format 'latexinfo-parse-arg-discard) (put 'bibliographystyle 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'pagestyle 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'pagenumbering 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'part 'latexinfo-format 'latexinfo-discard-line-with-args) (put 'cpsubindex 'latexinfo-format 'latexinfo-discard-line-with-args) ;;; Catchall for latexinfo-format-region (put 'documentstyle 'latexinfo-format 'latexinfo-discard-line-with-args) ;;; Titlepage commands ;; Author (put 'author 'latexinfo-format 'latexinfo-format-author) (defun latexinfo-format-author () (latexinfo-format-atd "author")) (put 'and 'latexinfo-format 'latexinfo-format-and) ;; This should really only be valid in titles. (defun latexinfo-format-and () (latexinfo-parse-noarg) (insert ?\n)) ;; title (put 'title 'latexinfo-format 'latexinfo-format-title) (defun latexinfo-format-title () (latexinfo-format-atd "title")) (put 'date 'latexinfo-format 'latexinfo-format-date) (defun latexinfo-format-date () (latexinfo-format-atd "date")) (defun latexinfo-format-atd (atd) (delete-region latexinfo-command-start latexinfo-command-end) (latexinfo-push-stack 'center 0) (if (looking-at "{") (save-excursion (let ((here (point)) (str nil)) (forward-sexp 1) (delete-char -1) (insert ?\n "\\end{center}") (goto-char here) (delete-char 1)) (goto-char latexinfo-command-start)) (error "No argument specified to the %s command" atd)) ) ;;\today (put 'today 'latexinfo-format 'latexinfo-format-today) (defun latexinfo-format-today () (delete-region latexinfo-command-start latexinfo-command-end) (let* ((date-string (current-time-string)) (month-alist '(("Jan" . "January") ("Feb" . "February") ("Mar" . "March") ("Apr" . "April") ("May" . "May") ("Jun" . "June") ("Jul" . "July") ("Aug" . "August") ("Sep" . "September") ("Oct" . "October") ("Nov" . "November") ("Dec" . "December"))) ) (string-match "\\(...\\) \\(...\\) \\(..\\).*\\(19..\\)" (current-time-string) nil) (insert (concat (cdr (assoc (substring date-string (match-beginning 2) (match-end 2)) month-alist)) " " (substring date-string (match-beginning 3) (match-end 3)) ", " (substring date-string (match-beginning 4) (match-end 4)) )) ) ) (put 'maketitle 'latexinfo-format 'latexinfo-format-maketitle) (defun latexinfo-format-maketitle () (latexinfo-parse-noarg)) (put 'finalout 'latexinfo-format 'latexinfo-format-finalout) (defun latexinfo-format-finalout () (latexinfo-parse-noarg)) (put 'sloppy 'latexinfo-format 'latexinfo-format-sloppy) (defun latexinfo-format-sloppy () (latexinfo-parse-noarg)) ;;; Bibliography (put 'bibliography 'latexinfo-format 'latexinfo-format-bibliography) (defun latexinfo-format-bibliography () (let* ((arg (latexinfo-parse-arg-discard)) (latexinfo-bbl-filename (expand-file-name (concat arg ".bbl"))) (here (point))) (eat-sexp) ;; This should be a chapter or a section. (insert "\\chapter*{References}" ?\n ?\n) (if (file-exists-p latexinfo-bbl-filename) (progn (insert-file latexinfo-bbl-filename) (exchange-point-and-mark) (narrow-to-region here (point)) (goto-char (point-min)) (quietly-replace-string "{\\em " "\\var{") (goto-char (point-min)) (quietly-replace-string "{\\it " "\\emph{") (goto-char (point-min)) (quietly-replace-string "{ " "\\r{") (widen) (goto-char latexinfo-command-start) ) (message "Formatted bibliography file not found: %s" latexinfo-bbl-filename)) ) ) (put 'thebibliography 'latexinfo-format 'latexinfo-thebibliography) (defun latexinfo-thebibliography () (if (looking-at "}") (forward-char 1)) (eat-sexp) (latexinfo-push-stack 'description "") (setq fill-column (- fill-column 5)) (latexinfo-discard-line)) (put 'thebibliography 'latexinfo-end 'latexinfo-end-description) (put 'bibitem 'latexinfo-format 'latexinfo-description-bibitem) (defun latexinfo-description-bibitem () (if (looking-at "}") (forward-char 1)) (eat-sexp) (let ((arg (latexinfo-parse-arg-discard))) (insert ?\b arg "\n \n")) (forward-line -2)) (put 'newblock 'latexinfo-format 'latexinfo-parse-noarg) (defun eat-sexp () (delete-region (point) (save-excursion (forward-sexp 1) (point)))) (provide 'latexinfo) ;;; Shut Emacs up about setting the mark. (defun quietly-replace-string (from-string to-string &optional delimited) "\ Replace occurrences of FROM-STRING with TO-STRING. Preserve case in each match if case-replace and case-fold-search are non-nil and FROM-STRING has no uppercase letters. Third arg DELIMITED (prefix arg if interactive) non-nil means replace only matches surrounded by word boundaries." (quietly-perform-replace from-string to-string nil nil delimited) ) (defun quietly-replace-regexp (regexp to-string &optional delimited) "\ Replace things after point matching REGEXP with TO-STRING. Preserve case in each match if case-replace and case-fold-search are non-nil and REGEXP has no uppercase letters. Third arg DELIMITED (prefix arg if interactive) non-nil means replace only matches surrounded by word boundaries. In TO-STRING, \\& means insert what matched REGEXP, and \\=\\ means insert what matched th \\(...\\) in REGEXP." (quietly-perform-replace regexp to-string nil t delimited) ) (defun quietly-push-mark (&optional location nomsg) "Set mark at LOCATION (point, by default) and push old mark on mark ring. Displays \"Mark set\" unless the optional second arg NOMSG is non-nil." (if (null (mark)) nil (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring)) (if (> (length mark-ring) mark-ring-max) (progn (move-marker (car (nthcdr mark-ring-max mark-ring)) nil) (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil)))) (set-mark (or location (point))) ) (defun quietly-perform-replace (from-string to-string query-flag regexp-flag delimited-flag) (let ((nocasify (not (and case-fold-search case-replace (string-equal from-string (downcase from-string))))) (literal (not regexp-flag)) (search-function (if regexp-flag 're-search-forward 'search-forward)) (search-string from-string) (keep-going t) (lastrepl nil)) ;Position after last match considered. (if delimited-flag (setq search-function 're-search-forward search-string (concat "\\b" (if regexp-flag from-string (regexp-quote from-string)) "\\b"))) (quietly-push-mark (point) t) (quietly-push-mark (point) t) (while (and keep-going (not (eobp)) (progn (set-mark (point)) (funcall search-function search-string nil t))) ;; Don't replace the null string ;; right after end of previous replacement. (if (eq lastrepl (point)) (forward-char 1) (undo-boundary) (if (not query-flag) (replace-match to-string nocasify literal) (let (done replaced) (while (not done) ;; Preserve the match data. Process filters and sentinels ;; could run inside read-char.. (let ((data (match-data)) (help-form '(concat "Query replacing " (if regexp-flag "regexp " "") from-string " with " to-string ".\n\n" (substitute-command-keys query-replace-help)))) (setq char help-char) (while (= char help-char) (message "Query replacing %s with %s: " from-string to-string) (setq char (read-char)) (if (= char ??) (setq unread-command-char help-char char help-char))) (store-match-data data)) (cond ((or (= char ?\e) (= char ?q)) (setq keep-going nil) (setq done t)) ((= char ?^) (goto-char (mark)) (setq replaced t)) ((or (= char ?\ ) (= char ?y)) (or replaced (replace-match to-string nocasify literal)) (setq done t)) ((= char ?\.) (or replaced (replace-match to-string nocasify literal)) (setq keep-going nil) (setq done t)) ((= char ?\,) (if (not replaced) (progn (replace-match to-string nocasify literal) (setq replaced t)))) ((= char ?!) (or replaced (replace-match to-string nocasify literal)) (setq done t query-flag nil)) ((or (= char ?\177) (= char ?n)) (setq done t)) ((= char ?\C-l) (recenter nil)) ((= char ?\C-r) (store-match-data (prog1 (match-data) (save-excursion (recursive-edit))))) ((= char ?\C-w) (delete-region (match-beginning 0) (match-end 0)) (store-match-data (prog1 (match-data) (save-excursion (recursive-edit)))) (setq replaced t)) (t (setq keep-going nil) (setq unread-command-char char) (setq done t)))))) (setq lastrepl (point)))) (pop-mark) keep-going)) ;; The overall process is one of: ;; (latexinfo-insert-node-lines (point-min) (point-max) t) ;; (mark-whole-buffer) ;; (latexinfo-sequential-node-update t) ;; (latexinfo-all-menus-update) ;; (latexinfo-master-menu nil) ;; (latexinfo-format-buffer t)