makeinfo.el 10.1 KB
Newer Older
Richard M. Stallman's avatar
Richard M. Stallman committed
1
;;; makeinfo.el --- run makeinfo conveniently
Richard M. Stallman's avatar
Richard M. Stallman committed
2

3
;; Copyright (C) 1991, 1993, 2002 Free Software Foundation, Inc.
Richard M. Stallman's avatar
Richard M. Stallman committed
4

5
;; Author: Robert J. Chassell
Richard M. Stallman's avatar
Richard M. Stallman committed
6
;; Maintainer: FSF
7
;; Keywords: docs convenience
Richard M. Stallman's avatar
Richard M. Stallman committed
8 9

;; This file is part of GNU Emacs.
Richard M. Stallman's avatar
Richard M. Stallman committed
10 11 12 13 14 15 16 17 18 19 20 21

;; 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
Erik Naggum's avatar
Erik Naggum committed
22 23 24
;; 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.
Richard M. Stallman's avatar
Richard M. Stallman committed
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49

;;; 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)
50
(require 'info)
Richard M. Stallman's avatar
Richard M. Stallman committed
51

52
(defgroup makeinfo nil
53
  "Run makeinfo conveniently."
54 55 56 57
  :group 'docs)


(defcustom makeinfo-run-command "makeinfo"
Richard M. Stallman's avatar
Richard M. Stallman committed
58
  "*Command used to run `makeinfo' subjob.
59 60 61
The name of the file is appended to this string, separated by a space."
  :type 'string
  :group 'makeinfo)
Richard M. Stallman's avatar
Richard M. Stallman committed
62

63
(defcustom makeinfo-options "--fill-column=70"
64
  "*String containing options for running `makeinfo'.
Richard M. Stallman's avatar
Richard M. Stallman committed
65 66
Do not include `--footnote-style' or `--paragraph-indent';
the proper way to specify those is with the Texinfo commands
67 68 69
`@footnotestyle` and `@paragraphindent'."
  :type 'string
  :group 'makeinfo)
Richard M. Stallman's avatar
Richard M. Stallman committed
70 71 72 73 74 75 76 77 78 79 80 81

(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'.")

82 83 84
(defvar makeinfo-output-node-name nil
  "Node name to visit in output file, for `makeinfo-buffer'.")

Richard M. Stallman's avatar
Richard M. Stallman committed
85 86 87 88 89 90 91 92 93

;;; 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 would
apply to a temporary file, not the original; use the `makeinfo-buffer'
command to gain use of `next-error'."
94

Richard M. Stallman's avatar
Richard M. Stallman committed
95 96 97 98 99 100 101 102 103 104
  (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
Stefan Monnier's avatar
Stefan Monnier committed
105
           (make-temp-file
Richard M. Stallman's avatar
Richard M. Stallman committed
106
            (substring (buffer-file-name)
107 108
                       0
                       (or (string-match "\\.tex" (buffer-file-name))
Richard M. Stallman's avatar
Richard M. Stallman committed
109 110
                           (length (buffer-file-name)))))
           ".texinfo"))
111

Richard M. Stallman's avatar
Richard M. Stallman committed
112 113 114 115 116 117 118
    (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.
119
          (if (re-search-forward
Richard M. Stallman's avatar
Richard M. Stallman committed
120 121
               "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*"
               search-end t)
122
              (setq makeinfo-output-file-name
Richard M. Stallman's avatar
Richard M. Stallman committed
123 124 125 126 127 128
                    (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))
129 130
          (if (and
               (prog1
131
                   (search-forward tex-start-of-header search-end t)
Richard M. Stallman's avatar
Richard M. Stallman committed
132 133 134
                 (beginning-of-line)
                 ;; Mark beginning of header.
                 (setq filename-or-header-beginning (point)))
135
               (prog1
136
                   (search-forward tex-end-of-header nil t)
Richard M. Stallman's avatar
Richard M. Stallman committed
137 138 139
                 (beginning-of-line)
                 ;; Mark end of header
                 (setq filename-or-header-end (point))))
140

Richard M. Stallman's avatar
Richard M. Stallman committed
141 142 143 144 145
              ;; 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)
146

Richard M. Stallman's avatar
Richard M. Stallman committed
147 148 149 150 151 152 153 154 155 156 157
            ;; 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))
158

Richard M. Stallman's avatar
Richard M. Stallman committed
159 160 161 162 163 164 165 166 167 168 169 170
          ;; 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
171
                     " "
Richard M. Stallman's avatar
Richard M. Stallman committed
172
                     makeinfo-temp-file)
173
             "Use `makeinfo-buffer' to gain use of the `next-error' command"
174 175
	     nil
             'makeinfo-compilation-sentinel-region)))))))
176 177 178 179

;;; 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.
180
(defun makeinfo-compile (command error-message parse-errors sentinel)
181 182 183 184 185 186
  (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.
187 188
				(lambda (&rest ignore)
				  (setq compilation-error-list nil))))))
189
    (set-process-sentinel (get-buffer-process buffer) sentinel)))
190 191

;; Delete makeinfo-temp-file after processing is finished,
Richard M. Stallman's avatar
Richard M. Stallman committed
192 193 194
;; and visit Info file.
;; This function is called when the compilation process changes state.
;; Based on `compilation-sentinel' in compile.el
195 196
(defun makeinfo-compilation-sentinel-region (proc msg)
  "Sentinel for `makeinfo-compile' run from `makeinfo-region'."
197
  (compilation-sentinel proc msg)
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
  (when (memq (process-status proc) '(signal exit))
    (if (file-exists-p makeinfo-temp-file)
	(delete-file makeinfo-temp-file))
    ;; Always use the version on disk.
    (let ((buffer (get-file-buffer makeinfo-output-file-name)))
      (if buffer
	  (with-current-buffer buffer
	    (revert-buffer t t))
	(setq buffer (find-file-noselect makeinfo-output-file-name)))
      (if (window-dedicated-p (selected-window))
	  (switch-to-buffer-other-window buffer)
	(switch-to-buffer buffer)))
    (goto-char (point-min))))

(defun makeinfo-current-node ()
  "Return the name of the node containing point, in a texinfo file."
  (save-excursion
    (end-of-line)           ; in case point is at the start of an @node line
    (if (re-search-backward "^@node\\s-+\\([^,\n]+\\)" (point-min) t)
        (match-string 1)
      "Top")))
219 220

(defun makeinfo-buffer ()
Richard M. Stallman's avatar
Richard M. Stallman committed
221 222
  "Make Info file from current buffer.

223
Use the \\[next-error] command to move to the next error
224
\(if there are errors\)."
225

226
  (interactive)
Richard M. Stallman's avatar
Richard M. Stallman committed
227
  (cond ((null buffer-file-name)
228
         (error "Buffer not visiting any file"))
Richard M. Stallman's avatar
Richard M. Stallman committed
229 230 231
        ((buffer-modified-p)
         (if (y-or-n-p "Buffer modified; do you want to save it? ")
             (save-buffer))))
232

Richard M. Stallman's avatar
Richard M. Stallman committed
233 234 235 236 237
  ;; 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))))
238
      (if (re-search-forward
Richard M. Stallman's avatar
Richard M. Stallman committed
239 240
           "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*"
           search-end t)
241
          (setq makeinfo-output-file-name
242 243
                (expand-file-name
                 (buffer-substring (match-beginning 1) (match-end 1))))
Richard M. Stallman's avatar
Richard M. Stallman committed
244 245
        (error
         "The texinfo file needs a line saying: @setfilename <name>"))))
246
  (setq makeinfo-output-node-name (makeinfo-current-node))
247

Richard M. Stallman's avatar
Richard M. Stallman committed
248 249
  (save-excursion
    (makeinfo-compile
250 251 252
     (concat makeinfo-run-command " " makeinfo-options
             " " buffer-file-name)
     "No more errors."
253 254 255 256 257 258 259 260 261 262
     t
     'makeinfo-compilation-sentinel-buffer)))

(defun makeinfo-compilation-sentinel-buffer (proc msg)
  "Sentinel for `makeinfo-compile' run from `makeinfo-buffer'."
  (compilation-sentinel proc msg)
  (when (memq (process-status proc) '(signal exit))
    (when (file-exists-p makeinfo-output-file-name)
      (Info-revert-find-node
       makeinfo-output-file-name makeinfo-output-node-name))))
Richard M. Stallman's avatar
Richard M. Stallman committed
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284

(defun makeinfo-recenter-compilation-buffer (linenum)
  "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."
  (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)

Miles Bader's avatar
Miles Bader committed
285
;;; arch-tag: 5f810713-3de2-4e20-8030-4bc3dd0d9604
Richard M. Stallman's avatar
Richard M. Stallman committed
286
;;; makeinfo.el ends here