(require 'compile)
(defgroup makeinfo nil
"Run makeinfo conveniently"
:group 'docs)
(defcustom makeinfo-run-command "makeinfo"
"*Command used to run `makeinfo' subjob.
The name of the file is appended to this string, separated by a space."
:type 'string
:group 'makeinfo)
(defcustom 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'."
:type 'string
:group 'makeinfo)
(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'.")
(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'."
(interactive "r")
(let (filename-or-header
filename-or-header-beginning
filename-or-header-end)
(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))))
(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>"))
(goto-char (point-min))
(if (and
(prog1
(search-forward tex-start-of-header search-end t)
(beginning-of-line)
(setq filename-or-header-beginning (point)))
(prog1
(search-forward tex-end-of-header nil t)
(beginning-of-line)
(setq filename-or-header-end (point))))
(write-region
(min filename-or-header-beginning region-beginning)
filename-or-header-end
makeinfo-temp-file nil nil)
(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))
(write-region
(max region-beginning filename-or-header-end)
region-end
makeinfo-temp-file t nil)
(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)))))))
(defun makeinfo-compile (command error-message parse-errors)
(let ((buffer
(compile-internal command error-message nil
(and (not parse-errors)
'(lambda (&rest ignore)
(setq compilation-error-list nil))))))
(set-process-sentinel (get-buffer-process buffer)
'makeinfo-compilation-sentinel)))
(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))
(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))))
(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 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)
)))
(provide 'makeinfo)