;;;; makeinfo.el -- run makeinfo conveniently.;;; Copyright (C) 1991, 1993 Free Software Foundation, Inc.;;; Author: Robert J. Chassell ;;; Maintainer: FSF;;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.;;; Commentary:;;; The Texinfo mode `makeinfo' related commands are:;; makeinfo-region to run makeinfo on the current region.;; makeinfo-buffer to run makeinfo on the current buffer, or;; with optional prefix arg, on current region;; kill-compilation to kill currently running makeinfo job;; makeinfo-recenter-makeinfo-buffer to redisplay *compilation* buffer;;; Keybindings (defined in `texinfo.el');; makeinfo bindings; (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); (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);;; Code:;;; Variables used by `makeinfo'(require 'compile)(defvar makeinfo-run-command "makeinfo" "*Command used to run `makeinfo' subjob.The name of the file is appended to this string, separated by a space.")(defvar makeinfo-options "--fill-column=70" "*String containing options for running `makeinfo'. Do not include `--footnote-style' or `--paragraph-indent';the proper way to specify those is with the Texinfo commands`@footnotestyle` and `@paragraphindent'.")(require 'texinfo)(defvar makeinfo-compilation-process nil "Process that runs `makeinfo'. Should start out nil.")(defvar makeinfo-temp-file nil "Temporary file name used for text being sent as input to `makeinfo'.")(defvar makeinfo-output-file-name nil "Info file name used for text output by `makeinfo'.");;; The `makeinfo' function definitions(defun makeinfo-region (region-beginning region-end) "Make Info file from region of current Texinfo file, and switch to it.This command does not offer the `next-error' feature since it wouldapply to a temporary file, not the original; use the `makeinfo-buffer'command to gain use of `next-error'." (interactive "r") (let (filename-or-header filename-or-header-beginning filename-or-header-end) ;; Cannot use `let' for makeinfo-temp-file or ;; makeinfo-output-file-name since `makeinfo-compilation-sentinel' ;; needs them. (setq makeinfo-temp-file (concat (make-temp-name (substring (buffer-file-name) 0 (or (string-match "\\.tex" (buffer-file-name)) (length (buffer-file-name))))) ".texinfo")) (save-excursion (save-restriction (widen) (goto-char (point-min)) (let ((search-end (save-excursion (forward-line 100) (point)))) ;; Find and record the Info filename, ;; or else explain that a filename is needed. (if (re-search-forward "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*" search-end t) (setq makeinfo-output-file-name (buffer-substring (match-beginning 1) (match-end 1))) (error "The texinfo file needs a line saying: @setfilename <name>")) ;; Find header and specify its beginning and end. (goto-char (point-min)) (if (and (prog1 (search-forward tex-start-of-header search-end t) (beginning-of-line) ;; Mark beginning of header. (setq filename-or-header-beginning (point))) (prog1 (search-forward tex-end-of-header nil t) (beginning-of-line) ;; Mark end of header (setq filename-or-header-end (point)))) ;; Insert the header into the temporary file. (write-region (min filename-or-header-beginning region-beginning) filename-or-header-end makeinfo-temp-file nil nil) ;; Else no header; insert @filename line into temporary file. (goto-char (point-min)) (search-forward "@setfilename" search-end t) (beginning-of-line) (setq filename-or-header-beginning (point)) (forward-line 1) (setq filename-or-header-end (point)) (write-region (min filename-or-header-beginning region-beginning) filename-or-header-end makeinfo-temp-file nil nil)) ;; Insert the region into the file. (write-region (max region-beginning filename-or-header-end) region-end makeinfo-temp-file t nil) ;; Run the `makeinfo-compile' command in the *compilation* buffer (save-excursion (makeinfo-compile (concat makeinfo-run-command " " makeinfo-options " " makeinfo-temp-file) "Use `makeinfo-buffer' to gain use of the `next-error' command" nil)))))));;; Actually run makeinfo. COMMAND is the command to run.;;; ERROR-MESSAGE is what to say when next-error can't find another error.;;; If PARSE-ERRORS is non-nil, do try to parse error messages.(defun makeinfo-compile (command error-message parse-errors) (let ((buffer (compile-internal command error-message nil (and (not parse-errors) ;; If we do want to parse errors, pass nil. ;; Otherwise, use this function, which won't ;; ever find any errors. '(lambda (&rest ignore) (setq compilation-error-list nil)))))) (set-process-sentinel (get-buffer-process buffer) 'makeinfo-compilation-sentinel)));; Delete makeinfo-temp-file after processing is finished,;; and visit Info file.;; This function is called when the compilation process changes state.;; Based on `compilation-sentinel' in compile.el(defun makeinfo-compilation-sentinel (proc msg) (compilation-sentinel proc msg) (if (and makeinfo-temp-file (file-exists-p makeinfo-temp-file)) (delete-file makeinfo-temp-file)) ;; Always use the version on disk. (if (get-file-buffer makeinfo-output-file-name) (progn (set-buffer makeinfo-output-file-name) (revert-buffer t t)) (find-file makeinfo-output-file-name)) (goto-char (point-min)))(defun makeinfo-buffer () "Make Info file from current buffer.Use the \\[next-error] command to move to the next error \(if there are errors\)." (interactive) (cond ((null buffer-file-name) (error "Buffer not visiting any file")) ((buffer-modified-p) (if (y-or-n-p "Buffer modified; do you want to save it? ") (save-buffer)))) ;; Find and record the Info filename, ;; or else explain that a filename is needed. (save-excursion (goto-char (point-min)) (let ((search-end (save-excursion (forward-line 100) (point)))) (if (re-search-forward "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*" search-end t) (setq makeinfo-output-file-name (buffer-substring (match-beginning 1) (match-end 1))) (error "The texinfo file needs a line saying: @setfilename <name>")))) (save-excursion (makeinfo-compile (concat makeinfo-run-command " " makeinfo-options " " buffer-file-name) "No more errors." t)))(defun makeinfo-recenter-compilation-buffer (linenum) "Redisplay `*compilation*' buffer so most recent output can be seen.The last line of the buffer is displayed online LINE of the window, or centered if LINE is nil." (interactive "P") (let ((makeinfo-buffer (get-buffer "*compilation*")) (old-buffer (current-buffer))) (if (null makeinfo-buffer) (message "No *compilation* buffer") (pop-to-buffer makeinfo-buffer) (bury-buffer makeinfo-buffer) (goto-char (point-max)) (recenter (if linenum (prefix-numeric-value linenum) (/ (window-height) 2))) (pop-to-buffer old-buffer) )));;; Place `provide' at end of file.(provide 'makeinfo);;; makeinfo.el ends here