Fix up comment convention on the arch-tag lines.
[bpt/emacs.git] / lisp / textmodes / makeinfo.el
CommitLineData
be010748 1;;; makeinfo.el --- run makeinfo conveniently
bab8cd70 2
f2e3589a 3;; Copyright (C) 1991, 1993, 2001, 2002, 2003, 2004,
12dc447f 4;; 2005, 2006, 2007, 2008 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
5a9dffec 14;; the Free Software Foundation; either version 3, or (at your option)
bab8cd70
RS
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
c5309fd6
JB
53(defvar tex-end-of-header)
54(defvar tex-start-of-header)
55
56
bbf5eb28 57(defgroup makeinfo nil
a7253b5a 58 "Run makeinfo conveniently."
bbf5eb28
RS
59 :group 'docs)
60
61
62(defcustom makeinfo-run-command "makeinfo"
bab8cd70 63 "*Command used to run `makeinfo' subjob.
bbf5eb28
RS
64The name of the file is appended to this string, separated by a space."
65 :type 'string
66 :group 'makeinfo)
bab8cd70 67
bbf5eb28 68(defcustom makeinfo-options "--fill-column=70"
db95369b 69 "*String containing options for running `makeinfo'.
bab8cd70
RS
70Do not include `--footnote-style' or `--paragraph-indent';
71the proper way to specify those is with the Texinfo commands
bbf5eb28
RS
72`@footnotestyle` and `@paragraphindent'."
73 :type 'string
74 :group 'makeinfo)
bab8cd70
RS
75
76(require 'texinfo)
bab8cd70
RS
77
78(defvar makeinfo-compilation-process nil
79 "Process that runs `makeinfo'. Should start out nil.")
80
81(defvar makeinfo-temp-file nil
82 "Temporary file name used for text being sent as input to `makeinfo'.")
83
84(defvar makeinfo-output-file-name nil
85 "Info file name used for text output by `makeinfo'.")
86
67f5dcb8
RS
87(defvar makeinfo-output-node-name nil
88 "Node name to visit in output file, for `makeinfo-buffer'.")
89
bab8cd70
RS
90\f
91;;; The `makeinfo' function definitions
92
93(defun makeinfo-region (region-beginning region-end)
94 "Make Info file from region of current Texinfo file, and switch to it.
95
96This command does not offer the `next-error' feature since it would
97apply to a temporary file, not the original; use the `makeinfo-buffer'
98command to gain use of `next-error'."
db95369b 99
bab8cd70
RS
100 (interactive "r")
101 (let (filename-or-header
102 filename-or-header-beginning
103 filename-or-header-end)
104 ;; Cannot use `let' for makeinfo-temp-file or
105 ;; makeinfo-output-file-name since `makeinfo-compilation-sentinel'
106 ;; needs them.
107
108 (setq makeinfo-temp-file
109 (concat
767d12f2 110 (make-temp-file
bab8cd70 111 (substring (buffer-file-name)
db95369b
JB
112 0
113 (or (string-match "\\.tex" (buffer-file-name))
bab8cd70
RS
114 (length (buffer-file-name)))))
115 ".texinfo"))
db95369b 116
bab8cd70
RS
117 (save-excursion
118 (save-restriction
119 (widen)
120 (goto-char (point-min))
121 (let ((search-end (save-excursion (forward-line 100) (point))))
122 ;; Find and record the Info filename,
123 ;; or else explain that a filename is needed.
db95369b 124 (if (re-search-forward
bab8cd70
RS
125 "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*"
126 search-end t)
db95369b 127 (setq makeinfo-output-file-name
bab8cd70
RS
128 (buffer-substring (match-beginning 1) (match-end 1)))
129 (error
130 "The texinfo file needs a line saying: @setfilename <name>"))
131
132 ;; Find header and specify its beginning and end.
133 (goto-char (point-min))
db95369b
JB
134 (if (and
135 (prog1
86c57d9f 136 (search-forward tex-start-of-header search-end t)
bab8cd70
RS
137 (beginning-of-line)
138 ;; Mark beginning of header.
139 (setq filename-or-header-beginning (point)))
db95369b 140 (prog1
86c57d9f 141 (search-forward tex-end-of-header nil t)
bab8cd70
RS
142 (beginning-of-line)
143 ;; Mark end of header
144 (setq filename-or-header-end (point))))
db95369b 145
bab8cd70
RS
146 ;; Insert the header into the temporary file.
147 (write-region
148 (min filename-or-header-beginning region-beginning)
149 filename-or-header-end
150 makeinfo-temp-file nil nil)
db95369b 151
bab8cd70
RS
152 ;; Else no header; insert @filename line into temporary file.
153 (goto-char (point-min))
154 (search-forward "@setfilename" search-end t)
155 (beginning-of-line)
156 (setq filename-or-header-beginning (point))
157 (forward-line 1)
158 (setq filename-or-header-end (point))
159 (write-region
160 (min filename-or-header-beginning region-beginning)
161 filename-or-header-end
162 makeinfo-temp-file nil nil))
db95369b 163
bab8cd70
RS
164 ;; Insert the region into the file.
165 (write-region
166 (max region-beginning filename-or-header-end)
167 region-end
168 makeinfo-temp-file t nil)
169
170 ;; Run the `makeinfo-compile' command in the *compilation* buffer
171 (save-excursion
172 (makeinfo-compile
173 (concat makeinfo-run-command
174 " "
175 makeinfo-options
db95369b 176 " "
bab8cd70 177 makeinfo-temp-file)
713fbb79 178 t
67f5dcb8 179 'makeinfo-compilation-sentinel-region)))))))
0f99112d 180
713fbb79
RF
181(defun makeinfo-next-error (arg reset)
182 "This function is used to disable `next-error' if the user has
183used `makeinfo-region'. Since the compilation process is used on
184a temporary file in that case, calling `next-error' would give
185nonsensical results."
186 (error "Use `makeinfo-buffer' to gain use of the `next-error' command"))
187
188;; Actually run makeinfo. COMMAND is the command to run. If
189;; DISABLE-ERRORS is non-nil, disable `next-error' by setting
190;; `next-error-function' to `makeinfo-next-error' in the compilation
191;; buffer.
192(defun makeinfo-compile (command disable-errors sentinel)
193 (let ((buffer (compilation-start command)))
194 (with-current-buffer buffer
195 (setq next-error-function
196 (if disable-errors
197 'makeinfo-next-error
198 'compilation-next-error-function)))
67f5dcb8 199 (set-process-sentinel (get-buffer-process buffer) sentinel)))
0f99112d
RS
200
201;; Delete makeinfo-temp-file after processing is finished,
bab8cd70
RS
202;; and visit Info file.
203;; This function is called when the compilation process changes state.
204;; Based on `compilation-sentinel' in compile.el
67f5dcb8
RS
205(defun makeinfo-compilation-sentinel-region (proc msg)
206 "Sentinel for `makeinfo-compile' run from `makeinfo-region'."
0f99112d 207 (compilation-sentinel proc msg)
67f5dcb8
RS
208 (when (memq (process-status proc) '(signal exit))
209 (if (file-exists-p makeinfo-temp-file)
210 (delete-file makeinfo-temp-file))
211 ;; Always use the version on disk.
212 (let ((buffer (get-file-buffer makeinfo-output-file-name)))
213 (if buffer
214 (with-current-buffer buffer
215 (revert-buffer t t))
216 (setq buffer (find-file-noselect makeinfo-output-file-name)))
217 (if (window-dedicated-p (selected-window))
218 (switch-to-buffer-other-window buffer)
219 (switch-to-buffer buffer)))
220 (goto-char (point-min))))
221
222(defun makeinfo-current-node ()
223 "Return the name of the node containing point, in a texinfo file."
224 (save-excursion
225 (end-of-line) ; in case point is at the start of an @node line
226 (if (re-search-backward "^@node\\s-+\\([^,\n]+\\)" (point-min) t)
227 (match-string 1)
228 "Top")))
0f99112d
RS
229
230(defun makeinfo-buffer ()
bab8cd70
RS
231 "Make Info file from current buffer.
232
db95369b 233Use the \\[next-error] command to move to the next error
0f99112d 234\(if there are errors\)."
db95369b 235
0f99112d 236 (interactive)
bab8cd70 237 (cond ((null buffer-file-name)
0f99112d 238 (error "Buffer not visiting any file"))
bab8cd70
RS
239 ((buffer-modified-p)
240 (if (y-or-n-p "Buffer modified; do you want to save it? ")
241 (save-buffer))))
db95369b 242
bab8cd70
RS
243 ;; Find and record the Info filename,
244 ;; or else explain that a filename is needed.
245 (save-excursion
246 (goto-char (point-min))
247 (let ((search-end (save-excursion (forward-line 100) (point))))
db95369b 248 (if (re-search-forward
bab8cd70
RS
249 "^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*"
250 search-end t)
db95369b 251 (setq makeinfo-output-file-name
67f5dcb8
RS
252 (expand-file-name
253 (buffer-substring (match-beginning 1) (match-end 1))))
bab8cd70
RS
254 (error
255 "The texinfo file needs a line saying: @setfilename <name>"))))
67f5dcb8 256 (setq makeinfo-output-node-name (makeinfo-current-node))
db95369b 257
bab8cd70
RS
258 (save-excursion
259 (makeinfo-compile
0f99112d 260 (concat makeinfo-run-command " " makeinfo-options
713fbb79
RF
261 " " buffer-file-name)
262 nil
67f5dcb8
RS
263 'makeinfo-compilation-sentinel-buffer)))
264
265(defun makeinfo-compilation-sentinel-buffer (proc msg)
266 "Sentinel for `makeinfo-compile' run from `makeinfo-buffer'."
267 (compilation-sentinel proc msg)
268 (when (memq (process-status proc) '(signal exit))
269 (when (file-exists-p makeinfo-output-file-name)
270 (Info-revert-find-node
271 makeinfo-output-file-name makeinfo-output-node-name))))
bab8cd70
RS
272
273(defun makeinfo-recenter-compilation-buffer (linenum)
274 "Redisplay `*compilation*' buffer so most recent output can be seen.
275The last line of the buffer is displayed on
276line LINE of the window, or centered if LINE is nil."
277 (interactive "P")
278 (let ((makeinfo-buffer (get-buffer "*compilation*"))
279 (old-buffer (current-buffer)))
280 (if (null makeinfo-buffer)
281 (message "No *compilation* buffer")
282 (pop-to-buffer makeinfo-buffer)
283 (bury-buffer makeinfo-buffer)
284 (goto-char (point-max))
285 (recenter (if linenum
286 (prefix-numeric-value linenum)
287 (/ (window-height) 2)))
288 (pop-to-buffer old-buffer)
289 )))
290
bab8cd70
RS
291;;; Place `provide' at end of file.
292(provide 'makeinfo)
293
cbee283d 294;; arch-tag: 5f810713-3de2-4e20-8030-4bc3dd0d9604
bab8cd70 295;;; makeinfo.el ends here