(makeinfo-compile): Use `compilation-start'. Set `next-error-function'
[bpt/emacs.git] / lisp / textmodes / makeinfo.el
CommitLineData
be010748 1;;; makeinfo.el --- run makeinfo conveniently
bab8cd70 2
3731a850
TTN
3;; Copyright (C) 1991, 1993, 2002, 2003, 2004,
4;; 2005 Free Software Foundation, Inc.
bab8cd70 5
db95369b 6;; Author: Robert J. Chassell
be010748 7;; Maintainer: FSF
6228c05b 8;; Keywords: docs convenience
be010748
RS
9
10;; This file is part of GNU Emacs.
bab8cd70
RS
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
b578f267 23;; along with GNU Emacs; see the file COPYING. If not, write to the
4fc5845f
LK
24;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25;; Boston, MA 02110-1301, USA.
bab8cd70
RS
26
27;;; Commentary:
28
29;;; The Texinfo mode `makeinfo' related commands are:
30
31;; makeinfo-region to run makeinfo on the current region.
32;; makeinfo-buffer to run makeinfo on the current buffer, or
33;; with optional prefix arg, on current region
34;; kill-compilation to kill currently running makeinfo job
35;; makeinfo-recenter-makeinfo-buffer to redisplay *compilation* buffer
36
37;;; Keybindings (defined in `texinfo.el')
38
39;; makeinfo bindings
40; (define-key texinfo-mode-map "\C-c\C-m\C-r" 'makeinfo-region)
41; (define-key texinfo-mode-map "\C-c\C-m\C-b" 'makeinfo-buffer)
42; (define-key texinfo-mode-map "\C-c\C-m\C-k" 'kill-compilation)
43; (define-key texinfo-mode-map "\C-c\C-m\C-l"
44; 'makeinfo-recenter-compilation-buffer)
45\f
46;;; Code:
47
48;;; Variables used by `makeinfo'
49
50(require 'compile)
67f5dcb8 51(require 'info)
bab8cd70 52
bbf5eb28 53(defgroup makeinfo nil
a7253b5a 54 "Run makeinfo conveniently."
bbf5eb28
RS
55 :group 'docs)
56
57
58(defcustom makeinfo-run-command "makeinfo"
bab8cd70 59 "*Command used to run `makeinfo' subjob.
bbf5eb28
RS
60The name of the file is appended to this string, separated by a space."
61 :type 'string
62 :group 'makeinfo)
bab8cd70 63
bbf5eb28 64(defcustom makeinfo-options "--fill-column=70"
db95369b 65 "*String containing options for running `makeinfo'.
bab8cd70
RS
66Do not include `--footnote-style' or `--paragraph-indent';
67the proper way to specify those is with the Texinfo commands
bbf5eb28
RS
68`@footnotestyle` and `@paragraphindent'."
69 :type 'string
70 :group 'makeinfo)
bab8cd70
RS
71
72(require 'texinfo)
bab8cd70
RS
73
74(defvar makeinfo-compilation-process nil
75 "Process that runs `makeinfo'. Should start out nil.")
76
77(defvar makeinfo-temp-file nil
78 "Temporary file name used for text being sent as input to `makeinfo'.")
79
80(defvar makeinfo-output-file-name nil
81 "Info file name used for text output by `makeinfo'.")
82
67f5dcb8
RS
83(defvar makeinfo-output-node-name nil
84 "Node name to visit in output file, for `makeinfo-buffer'.")
85
bab8cd70
RS
86\f
87;;; The `makeinfo' function definitions
88
89(defun makeinfo-region (region-beginning region-end)
90 "Make Info file from region of current Texinfo file, and switch to it.
91
92This command does not offer the `next-error' feature since it would
93apply to a temporary file, not the original; use the `makeinfo-buffer'
94command to gain use of `next-error'."
db95369b 95
bab8cd70
RS
96 (interactive "r")
97 (let (filename-or-header
98 filename-or-header-beginning
99 filename-or-header-end)
100 ;; Cannot use `let' for makeinfo-temp-file or
101 ;; makeinfo-output-file-name since `makeinfo-compilation-sentinel'
102 ;; needs them.
103
104 (setq makeinfo-temp-file
105 (concat
767d12f2 106 (make-temp-file
bab8cd70 107 (substring (buffer-file-name)
db95369b
JB
108 0
109 (or (string-match "\\.tex" (buffer-file-name))
bab8cd70
RS
110 (length (buffer-file-name)))))
111 ".texinfo"))
db95369b 112
bab8cd70
RS
113 (save-excursion
114 (save-restriction
115 (widen)
116 (goto-char (point-min))
117 (let ((search-end (save-excursion (forward-line 100) (point))))
118 ;; Find and record the Info filename,
119 ;; or else explain that a filename is needed.
db95369b 120 (if (re-search-forward
bab8cd70
RS
121 "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*"
122 search-end t)
db95369b 123 (setq makeinfo-output-file-name
bab8cd70
RS
124 (buffer-substring (match-beginning 1) (match-end 1)))
125 (error
126 "The texinfo file needs a line saying: @setfilename <name>"))
127
128 ;; Find header and specify its beginning and end.
129 (goto-char (point-min))
db95369b
JB
130 (if (and
131 (prog1
86c57d9f 132 (search-forward tex-start-of-header search-end t)
bab8cd70
RS
133 (beginning-of-line)
134 ;; Mark beginning of header.
135 (setq filename-or-header-beginning (point)))
db95369b 136 (prog1
86c57d9f 137 (search-forward tex-end-of-header nil t)
bab8cd70
RS
138 (beginning-of-line)
139 ;; Mark end of header
140 (setq filename-or-header-end (point))))
db95369b 141
bab8cd70
RS
142 ;; Insert the header into the temporary file.
143 (write-region
144 (min filename-or-header-beginning region-beginning)
145 filename-or-header-end
146 makeinfo-temp-file nil nil)
db95369b 147
bab8cd70
RS
148 ;; Else no header; insert @filename line into temporary file.
149 (goto-char (point-min))
150 (search-forward "@setfilename" search-end t)
151 (beginning-of-line)
152 (setq filename-or-header-beginning (point))
153 (forward-line 1)
154 (setq filename-or-header-end (point))
155 (write-region
156 (min filename-or-header-beginning region-beginning)
157 filename-or-header-end
158 makeinfo-temp-file nil nil))
db95369b 159
bab8cd70
RS
160 ;; Insert the region into the file.
161 (write-region
162 (max region-beginning filename-or-header-end)
163 region-end
164 makeinfo-temp-file t nil)
165
166 ;; Run the `makeinfo-compile' command in the *compilation* buffer
167 (save-excursion
168 (makeinfo-compile
169 (concat makeinfo-run-command
170 " "
171 makeinfo-options
db95369b 172 " "
bab8cd70 173 makeinfo-temp-file)
713fbb79 174 t
67f5dcb8 175 'makeinfo-compilation-sentinel-region)))))))
0f99112d 176
713fbb79
RF
177(defun makeinfo-next-error (arg reset)
178 "This function is used to disable `next-error' if the user has
179used `makeinfo-region'. Since the compilation process is used on
180a temporary file in that case, calling `next-error' would give
181nonsensical results."
182 (error "Use `makeinfo-buffer' to gain use of the `next-error' command"))
183
184;; Actually run makeinfo. COMMAND is the command to run. If
185;; DISABLE-ERRORS is non-nil, disable `next-error' by setting
186;; `next-error-function' to `makeinfo-next-error' in the compilation
187;; buffer.
188(defun makeinfo-compile (command disable-errors sentinel)
189 (let ((buffer (compilation-start command)))
190 (with-current-buffer buffer
191 (setq next-error-function
192 (if disable-errors
193 'makeinfo-next-error
194 'compilation-next-error-function)))
67f5dcb8 195 (set-process-sentinel (get-buffer-process buffer) sentinel)))
0f99112d
RS
196
197;; Delete makeinfo-temp-file after processing is finished,
bab8cd70
RS
198;; and visit Info file.
199;; This function is called when the compilation process changes state.
200;; Based on `compilation-sentinel' in compile.el
67f5dcb8
RS
201(defun makeinfo-compilation-sentinel-region (proc msg)
202 "Sentinel for `makeinfo-compile' run from `makeinfo-region'."
0f99112d 203 (compilation-sentinel proc msg)
67f5dcb8
RS
204 (when (memq (process-status proc) '(signal exit))
205 (if (file-exists-p makeinfo-temp-file)
206 (delete-file makeinfo-temp-file))
207 ;; Always use the version on disk.
208 (let ((buffer (get-file-buffer makeinfo-output-file-name)))
209 (if buffer
210 (with-current-buffer buffer
211 (revert-buffer t t))
212 (setq buffer (find-file-noselect makeinfo-output-file-name)))
213 (if (window-dedicated-p (selected-window))
214 (switch-to-buffer-other-window buffer)
215 (switch-to-buffer buffer)))
216 (goto-char (point-min))))
217
218(defun makeinfo-current-node ()
219 "Return the name of the node containing point, in a texinfo file."
220 (save-excursion
221 (end-of-line) ; in case point is at the start of an @node line
222 (if (re-search-backward "^@node\\s-+\\([^,\n]+\\)" (point-min) t)
223 (match-string 1)
224 "Top")))
0f99112d
RS
225
226(defun makeinfo-buffer ()
bab8cd70
RS
227 "Make Info file from current buffer.
228
db95369b 229Use the \\[next-error] command to move to the next error
0f99112d 230\(if there are errors\)."
db95369b 231
0f99112d 232 (interactive)
bab8cd70 233 (cond ((null buffer-file-name)
0f99112d 234 (error "Buffer not visiting any file"))
bab8cd70
RS
235 ((buffer-modified-p)
236 (if (y-or-n-p "Buffer modified; do you want to save it? ")
237 (save-buffer))))
db95369b 238
bab8cd70
RS
239 ;; Find and record the Info filename,
240 ;; or else explain that a filename is needed.
241 (save-excursion
242 (goto-char (point-min))
243 (let ((search-end (save-excursion (forward-line 100) (point))))
db95369b 244 (if (re-search-forward
bab8cd70
RS
245 "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*"
246 search-end t)
db95369b 247 (setq makeinfo-output-file-name
67f5dcb8
RS
248 (expand-file-name
249 (buffer-substring (match-beginning 1) (match-end 1))))
bab8cd70
RS
250 (error
251 "The texinfo file needs a line saying: @setfilename <name>"))))
67f5dcb8 252 (setq makeinfo-output-node-name (makeinfo-current-node))
db95369b 253
bab8cd70
RS
254 (save-excursion
255 (makeinfo-compile
0f99112d 256 (concat makeinfo-run-command " " makeinfo-options
713fbb79
RF
257 " " buffer-file-name)
258 nil
67f5dcb8
RS
259 'makeinfo-compilation-sentinel-buffer)))
260
261(defun makeinfo-compilation-sentinel-buffer (proc msg)
262 "Sentinel for `makeinfo-compile' run from `makeinfo-buffer'."
263 (compilation-sentinel proc msg)
264 (when (memq (process-status proc) '(signal exit))
265 (when (file-exists-p makeinfo-output-file-name)
266 (Info-revert-find-node
267 makeinfo-output-file-name makeinfo-output-node-name))))
bab8cd70
RS
268
269(defun makeinfo-recenter-compilation-buffer (linenum)
270 "Redisplay `*compilation*' buffer so most recent output can be seen.
271The last line of the buffer is displayed on
272line LINE of the window, or centered if LINE is nil."
273 (interactive "P")
274 (let ((makeinfo-buffer (get-buffer "*compilation*"))
275 (old-buffer (current-buffer)))
276 (if (null makeinfo-buffer)
277 (message "No *compilation* buffer")
278 (pop-to-buffer makeinfo-buffer)
279 (bury-buffer makeinfo-buffer)
280 (goto-char (point-max))
281 (recenter (if linenum
282 (prefix-numeric-value linenum)
283 (/ (window-height) 2)))
284 (pop-to-buffer old-buffer)
285 )))
286
bab8cd70
RS
287;;; Place `provide' at end of file.
288(provide 'makeinfo)
289
ab5796a9 290;;; arch-tag: 5f810713-3de2-4e20-8030-4bc3dd0d9604
bab8cd70 291;;; makeinfo.el ends here