1 |
;;; makeinfo.el --- run makeinfo conveniently |
;;; makeinfo.el --- run makeinfo conveniently |
2 |
|
|
3 |
;; Copyright (C) 1991, 1993 Free Software Foundation, Inc. |
;; Copyright (C) 1991, 1993, 2002 Free Software Foundation, Inc. |
4 |
|
|
5 |
;; Author: Robert J. Chassell |
;; Author: Robert J. Chassell |
6 |
;; Maintainer: FSF |
;; Maintainer: FSF |
7 |
;; Keywords: docs convenience |
;; Keywords: docs convenience |
8 |
|
|
47 |
;;; Variables used by `makeinfo' |
;;; Variables used by `makeinfo' |
48 |
|
|
49 |
(require 'compile) |
(require 'compile) |
50 |
|
(require 'info) |
51 |
|
|
52 |
(defgroup makeinfo nil |
(defgroup makeinfo nil |
53 |
"Run makeinfo conveniently" |
"Run makeinfo conveniently" |
61 |
:group 'makeinfo) |
:group 'makeinfo) |
62 |
|
|
63 |
(defcustom makeinfo-options "--fill-column=70" |
(defcustom makeinfo-options "--fill-column=70" |
64 |
"*String containing options for running `makeinfo'. |
"*String containing options for running `makeinfo'. |
65 |
Do not include `--footnote-style' or `--paragraph-indent'; |
Do not include `--footnote-style' or `--paragraph-indent'; |
66 |
the proper way to specify those is with the Texinfo commands |
the proper way to specify those is with the Texinfo commands |
67 |
`@footnotestyle` and `@paragraphindent'." |
`@footnotestyle` and `@paragraphindent'." |
79 |
(defvar makeinfo-output-file-name nil |
(defvar makeinfo-output-file-name nil |
80 |
"Info file name used for text output by `makeinfo'.") |
"Info file name used for text output by `makeinfo'.") |
81 |
|
|
82 |
|
(defvar makeinfo-output-node-name nil |
83 |
|
"Node name to visit in output file, for `makeinfo-buffer'.") |
84 |
|
|
85 |
|
|
86 |
;;; The `makeinfo' function definitions |
;;; The `makeinfo' function definitions |
87 |
|
|
91 |
This command does not offer the `next-error' feature since it would |
This command does not offer the `next-error' feature since it would |
92 |
apply to a temporary file, not the original; use the `makeinfo-buffer' |
apply to a temporary file, not the original; use the `makeinfo-buffer' |
93 |
command to gain use of `next-error'." |
command to gain use of `next-error'." |
94 |
|
|
95 |
(interactive "r") |
(interactive "r") |
96 |
(let (filename-or-header |
(let (filename-or-header |
97 |
filename-or-header-beginning |
filename-or-header-beginning |
104 |
(concat |
(concat |
105 |
(make-temp-file |
(make-temp-file |
106 |
(substring (buffer-file-name) |
(substring (buffer-file-name) |
107 |
0 |
0 |
108 |
(or (string-match "\\.tex" (buffer-file-name)) |
(or (string-match "\\.tex" (buffer-file-name)) |
109 |
(length (buffer-file-name))))) |
(length (buffer-file-name))))) |
110 |
".texinfo")) |
".texinfo")) |
111 |
|
|
112 |
(save-excursion |
(save-excursion |
113 |
(save-restriction |
(save-restriction |
114 |
(widen) |
(widen) |
116 |
(let ((search-end (save-excursion (forward-line 100) (point)))) |
(let ((search-end (save-excursion (forward-line 100) (point)))) |
117 |
;; Find and record the Info filename, |
;; Find and record the Info filename, |
118 |
;; or else explain that a filename is needed. |
;; or else explain that a filename is needed. |
119 |
(if (re-search-forward |
(if (re-search-forward |
120 |
"^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*" |
"^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*" |
121 |
search-end t) |
search-end t) |
122 |
(setq makeinfo-output-file-name |
(setq makeinfo-output-file-name |
123 |
(buffer-substring (match-beginning 1) (match-end 1))) |
(buffer-substring (match-beginning 1) (match-end 1))) |
124 |
(error |
(error |
125 |
"The texinfo file needs a line saying: @setfilename <name>")) |
"The texinfo file needs a line saying: @setfilename <name>")) |
126 |
|
|
127 |
;; Find header and specify its beginning and end. |
;; Find header and specify its beginning and end. |
128 |
(goto-char (point-min)) |
(goto-char (point-min)) |
129 |
(if (and |
(if (and |
130 |
(prog1 |
(prog1 |
131 |
(search-forward tex-start-of-header search-end t) |
(search-forward tex-start-of-header search-end t) |
132 |
(beginning-of-line) |
(beginning-of-line) |
133 |
;; Mark beginning of header. |
;; Mark beginning of header. |
134 |
(setq filename-or-header-beginning (point))) |
(setq filename-or-header-beginning (point))) |
135 |
(prog1 |
(prog1 |
136 |
(search-forward tex-end-of-header nil t) |
(search-forward tex-end-of-header nil t) |
137 |
(beginning-of-line) |
(beginning-of-line) |
138 |
;; Mark end of header |
;; Mark end of header |
139 |
(setq filename-or-header-end (point)))) |
(setq filename-or-header-end (point)))) |
140 |
|
|
141 |
;; Insert the header into the temporary file. |
;; Insert the header into the temporary file. |
142 |
(write-region |
(write-region |
143 |
(min filename-or-header-beginning region-beginning) |
(min filename-or-header-beginning region-beginning) |
144 |
filename-or-header-end |
filename-or-header-end |
145 |
makeinfo-temp-file nil nil) |
makeinfo-temp-file nil nil) |
146 |
|
|
147 |
;; Else no header; insert @filename line into temporary file. |
;; Else no header; insert @filename line into temporary file. |
148 |
(goto-char (point-min)) |
(goto-char (point-min)) |
149 |
(search-forward "@setfilename" search-end t) |
(search-forward "@setfilename" search-end t) |
155 |
(min filename-or-header-beginning region-beginning) |
(min filename-or-header-beginning region-beginning) |
156 |
filename-or-header-end |
filename-or-header-end |
157 |
makeinfo-temp-file nil nil)) |
makeinfo-temp-file nil nil)) |
158 |
|
|
159 |
;; Insert the region into the file. |
;; Insert the region into the file. |
160 |
(write-region |
(write-region |
161 |
(max region-beginning filename-or-header-end) |
(max region-beginning filename-or-header-end) |
168 |
(concat makeinfo-run-command |
(concat makeinfo-run-command |
169 |
" " |
" " |
170 |
makeinfo-options |
makeinfo-options |
171 |
" " |
" " |
172 |
makeinfo-temp-file) |
makeinfo-temp-file) |
173 |
"Use `makeinfo-buffer' to gain use of the `next-error' command" |
"Use `makeinfo-buffer' to gain use of the `next-error' command" |
174 |
nil))))))) |
nil |
175 |
|
'makeinfo-compilation-sentinel-region))))))) |
176 |
|
|
177 |
;;; Actually run makeinfo. COMMAND is the command to run. |
;;; Actually run makeinfo. COMMAND is the command to run. |
178 |
;;; ERROR-MESSAGE is what to say when next-error can't find another error. |
;;; ERROR-MESSAGE is what to say when next-error can't find another error. |
179 |
;;; If PARSE-ERRORS is non-nil, do try to parse error messages. |
;;; If PARSE-ERRORS is non-nil, do try to parse error messages. |
180 |
(defun makeinfo-compile (command error-message parse-errors) |
(defun makeinfo-compile (command error-message parse-errors sentinel) |
181 |
(let ((buffer |
(let ((buffer |
182 |
(compile-internal command error-message nil |
(compile-internal command error-message nil |
183 |
(and (not parse-errors) |
(and (not parse-errors) |
186 |
;; ever find any errors. |
;; ever find any errors. |
187 |
(lambda (&rest ignore) |
(lambda (&rest ignore) |
188 |
(setq compilation-error-list nil)))))) |
(setq compilation-error-list nil)))))) |
189 |
(set-process-sentinel (get-buffer-process buffer) |
(set-process-sentinel (get-buffer-process buffer) sentinel))) |
|
'makeinfo-compilation-sentinel))) |
|
190 |
|
|
191 |
;; Delete makeinfo-temp-file after processing is finished, |
;; Delete makeinfo-temp-file after processing is finished, |
192 |
;; and visit Info file. |
;; and visit Info file. |
193 |
;; This function is called when the compilation process changes state. |
;; This function is called when the compilation process changes state. |
194 |
;; Based on `compilation-sentinel' in compile.el |
;; Based on `compilation-sentinel' in compile.el |
195 |
(defun makeinfo-compilation-sentinel (proc msg) |
(defun makeinfo-compilation-sentinel-region (proc msg) |
196 |
|
"Sentinel for `makeinfo-compile' run from `makeinfo-region'." |
197 |
(compilation-sentinel proc msg) |
(compilation-sentinel proc msg) |
198 |
(if (and makeinfo-temp-file (file-exists-p makeinfo-temp-file)) |
(when (memq (process-status proc) '(signal exit)) |
199 |
(delete-file makeinfo-temp-file)) |
(if (file-exists-p makeinfo-temp-file) |
200 |
;; Always use the version on disk. |
(delete-file makeinfo-temp-file)) |
201 |
(let ((buffer (get-file-buffer makeinfo-output-file-name))) |
;; Always use the version on disk. |
202 |
(if buffer |
(let ((buffer (get-file-buffer makeinfo-output-file-name))) |
203 |
(with-current-buffer buffer |
(if buffer |
204 |
(revert-buffer t t)) |
(with-current-buffer buffer |
205 |
(setq buffer (find-file-noselect makeinfo-output-file-name))) |
(revert-buffer t t)) |
206 |
(if (window-dedicated-p (selected-window)) |
(setq buffer (find-file-noselect makeinfo-output-file-name))) |
207 |
(switch-to-buffer-other-window buffer) |
(if (window-dedicated-p (selected-window)) |
208 |
(switch-to-buffer buffer))) |
(switch-to-buffer-other-window buffer) |
209 |
(goto-char (point-min))) |
(switch-to-buffer buffer))) |
210 |
|
(goto-char (point-min)))) |
211 |
|
|
212 |
|
(defun makeinfo-current-node () |
213 |
|
"Return the name of the node containing point, in a texinfo file." |
214 |
|
(save-excursion |
215 |
|
(end-of-line) ; in case point is at the start of an @node line |
216 |
|
(if (re-search-backward "^@node\\s-+\\([^,\n]+\\)" (point-min) t) |
217 |
|
(match-string 1) |
218 |
|
"Top"))) |
219 |
|
|
220 |
(defun makeinfo-buffer () |
(defun makeinfo-buffer () |
221 |
"Make Info file from current buffer. |
"Make Info file from current buffer. |
222 |
|
|
223 |
Use the \\[next-error] command to move to the next error |
Use the \\[next-error] command to move to the next error |
224 |
\(if there are errors\)." |
\(if there are errors\)." |
225 |
|
|
226 |
(interactive) |
(interactive) |
227 |
(cond ((null buffer-file-name) |
(cond ((null buffer-file-name) |
228 |
(error "Buffer not visiting any file")) |
(error "Buffer not visiting any file")) |
229 |
((buffer-modified-p) |
((buffer-modified-p) |
230 |
(if (y-or-n-p "Buffer modified; do you want to save it? ") |
(if (y-or-n-p "Buffer modified; do you want to save it? ") |
231 |
(save-buffer)))) |
(save-buffer)))) |
232 |
|
|
233 |
;; Find and record the Info filename, |
;; Find and record the Info filename, |
234 |
;; or else explain that a filename is needed. |
;; or else explain that a filename is needed. |
235 |
(save-excursion |
(save-excursion |
236 |
(goto-char (point-min)) |
(goto-char (point-min)) |
237 |
(let ((search-end (save-excursion (forward-line 100) (point)))) |
(let ((search-end (save-excursion (forward-line 100) (point)))) |
238 |
(if (re-search-forward |
(if (re-search-forward |
239 |
"^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*" |
"^@setfilename[ \t]+\\([^ \t\n]+\\)[ \t]*" |
240 |
search-end t) |
search-end t) |
241 |
(setq makeinfo-output-file-name |
(setq makeinfo-output-file-name |
242 |
(buffer-substring (match-beginning 1) (match-end 1))) |
(expand-file-name |
243 |
|
(buffer-substring (match-beginning 1) (match-end 1)))) |
244 |
(error |
(error |
245 |
"The texinfo file needs a line saying: @setfilename <name>")))) |
"The texinfo file needs a line saying: @setfilename <name>")))) |
246 |
|
(setq makeinfo-output-node-name (makeinfo-current-node)) |
247 |
|
|
248 |
(save-excursion |
(save-excursion |
249 |
(makeinfo-compile |
(makeinfo-compile |
250 |
(concat makeinfo-run-command " " makeinfo-options |
(concat makeinfo-run-command " " makeinfo-options |
251 |
" " buffer-file-name) |
" " buffer-file-name) |
252 |
"No more errors." |
"No more errors." |
253 |
t))) |
t |
254 |
|
'makeinfo-compilation-sentinel-buffer))) |
255 |
|
|
256 |
|
(defun makeinfo-compilation-sentinel-buffer (proc msg) |
257 |
|
"Sentinel for `makeinfo-compile' run from `makeinfo-buffer'." |
258 |
|
(compilation-sentinel proc msg) |
259 |
|
(when (memq (process-status proc) '(signal exit)) |
260 |
|
(when (file-exists-p makeinfo-output-file-name) |
261 |
|
(Info-revert-find-node |
262 |
|
makeinfo-output-file-name makeinfo-output-node-name)))) |
263 |
|
|
264 |
(defun makeinfo-recenter-compilation-buffer (linenum) |
(defun makeinfo-recenter-compilation-buffer (linenum) |
265 |
"Redisplay `*compilation*' buffer so most recent output can be seen. |
"Redisplay `*compilation*' buffer so most recent output can be seen. |