[comp.emacs] background formatting & printing

ron@mlfarm.UUCP (Ronald Florence) (10/24/89)

Some time ago I posted a query about how to do troff formatting and
printing as a background (asynchronous) process under GNU Emacs.  I
received some useful suggestions by email, then put together the
attached code (format.el) which provides:

	troff-buffer	(troff to a printer)
	troff-region
	nroff-buffer	(nroff to a printer)
	nroff-region
	proof-buffer	(nroff proof to an Emacs window)
	tproof-buffer	(troff ascii proof to an Emacs window)
	pr-buffer	(pr to a printer)
	pr-region

The printer and proof processes all run in the background, and can be
interrupted with kill-print or kill-proof.  To use the package,
customize roff-macro, troff-options, nroff-options, and the format
strings to fit your local requirements.  If you do much work with troff
or nroff, you may want to load format.el in a new version of Emacs.
Zap-nroff-crap uses a local kluge to invoke expanded print for lines
beginning with ^G.

I welcome suggestions for changes or improvements.

_________________________________
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	format.el
# This archive created: Tue Oct 24 10:41:38 1989
# By:	Ronald Florence (Maple Lawn Farm, Stonington, CT)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'format.el'" '(7181 characters)'
if test -f 'format.el'
then
	echo shar: "will not over-write existing file 'format.el'"
else
sed 's/^X//' << \SHAR_EOF > 'format.el'
X;; format.el
X;; Copyright 1989 Ronald Florence (ron@mlfarm)
X
X(defvar roff-macro "-mm"
X"*Default macro package to use with troff and nroff.")
X
X(defvar troff-options "-rN2"
X"*Default options to use with troff.")
X
X(defvar nroff-options "-rN2 -rO9"
X"*Default options to use with nroff.")
X
X(setq troff-format-string "\(troff -t %s %s %s 2>&1 \) | lp -ot -n%d")
X(setq nroff-format-string "nroff -Thp %s %s %s | lp -n%d")
X(setq pr-format-string "pr -h %s %s | lp -n%d")
X
X(if (not nroff-mode-map)
X    (error "Nroff-mode is not loaded.")
X  (progn
X    (define-key nroff-mode-map "\C-c\C-n" 'proof-buffer)
X    (define-key nroff-mode-map "\C-c\C-t" 'tproof-buffer)
X    (define-key nroff-mode-map "\C-c\C-k" 'kill-proof)
X    (define-key nroff-mode-map "\C-c\C-i" 'kill-print)))
X
X(setq proof-tmp-file nil 
X      print-tmp-file nil
X      proof-process nil 
X      print-process nil
X      proof-file nil)
X
X(defun nroff-buffer (&optional copies)
X  "Print buffer contents after formatting with nroff.
XOptional prefix argument specifies number of copies."
X  (interactive "p")
X  (format-to-printer-region (point-min) (point-max) "nroff" copies))
X
X(defun nroff-region (start end &optional copies)
X  "Print region contents after formatting with nroff.
XOptional prefix argument specifies number of copies."
X  (interactive "r\np")
X  (format-to-printer-region start end "nroff" copies))
X
X(defun troff-buffer (&optional copies)
X  "Typeset buffer after formatting with troff.
XOptional prefix argument specifies number of copies."
X  (interactive "p")
X  (format-to-printer-region (point-min) (point-max) "troff" copies))
X
X(defun troff-region (start end &optional copies)
X  "Typeset region contents after formatting with troff.
XOptional prefix argument specifies number of copies."
X  (interactive "r\np")
X  (format-to-printer-region start end "troff" copies))
X
X(defun pr-buffer (&optional copies)
X  "Print buffer contents after formatting with pr.
XOptional prefix argument specifies number of copies."
X  (interactive "p")
X  (format-to-printer-region (point-min) (point-max) "pr" copies))
X
X(defun pr-region (start end &optional copies)
X  "Print region contents after formatting with pr.
XOptional prefix argument specifies number of copies."
X  (interactive "r\np")
X  (format-to-printer-region start end "pr" copies))
X
X(defun proof-region (start end)
X  "Proof region using nroff."
X  (interactive "r")
X  (proof-region-to-buffer start end "nroff"))
X
X(defun proof-buffer ()
X  "Proof buffer using nroff."
X  (interactive)
X  (proof-region-to-buffer (point-min) (point-max) "nroff"))
X
X(defun tproof-region (start end)
X  "Rough proof region using troff."
X  (interactive "r")
X  (proof-region-to-buffer start end "troff"))
X
X(defun tproof-buffer ()
X  "Rough proof buffer using troff."
X  (interactive)
X  (proof-region-to-buffer (point-min) (point-max) "troff"))
X
X(defun kill-print ()
X  "Kill format-to-printer process."
X  (interactive)
X  (if print-process
X      (interrupt-process print-process)))
X
X(defun kill-proof ()
X  "Kill proof process."
X  (interactive)
X  (if proof-process
X      (interrupt-process proof-process)))
X
X(defun format-to-printer-region (start end formatter &optional copies)
X  (if print-process
X      (if (or 
X	   (not (eq (process-status print-process) 'run))
X	   (yes-or-no-p "A format-to-printer process is running; kill it? "))
X	  (condition-case ()
X	      (let ((print-proc print-process))
X		(interrupt-process print-proc)
X		(sit-for 1)
X		(delete-process print-proc))
X	    (error nil))
X	(error "One format-to-printer process at a time.")))
X  (save-excursion
X    (setq printer-output-buffer " *printer output*")
X    (get-buffer-create printer-output-buffer)
X    (set-buffer printer-output-buffer)
X    (erase-buffer))
X  (if (null copies) (setq copies 1))
X  (setq print-tmp-file (concat "/tmp/" (make-temp-name "#pr#")))
X  (write-region start end print-tmp-file nil 'nomsg)
X  (setq print-command 
X	(cond ((string= formatter "troff")
X	       (format troff-format-string
X		       troff-options roff-macro
X		       print-tmp-file copies))
X	      ((string= formatter "nroff") 
X	       (format nroff-format-string
X		       nroff-options roff-macro
X		       print-tmp-file copies))
X	      ((string= formatter "pr")
X	       (format pr-format-string
X		       (buffer-name) print-tmp-file copies))))
X  (setq print-process
X	(start-process formatter printer-output-buffer "sh" "-c"
X		       print-command))
X  (set-process-sentinel print-process 'print-sentinel))
X
X(defun print-sentinel (process msg)
X  (delete-file print-tmp-file)
X  (save-excursion
X    (set-buffer (process-buffer process))
X    (if (> (buffer-size) 0)
X	(progn
X	  (goto-char (point-min))
X	  (end-of-line)
X	  (message "%s: %s" (process-name process) 
X		   (buffer-substring 1 (point))))
X      (message "%s: killed" (process-name process))))
X  (setq print-process nil)
X  (kill-buffer (process-buffer process)))
X
X(defun proof-region-to-buffer (start end formatter)
X  (if proof-process
X      (if (or (not (eq (process-status proof-process) 'run))
X	      (yes-or-no-p "A proof process is running; kill it? "))
X	  (condition-case ()
X	      (let ((proof-proc proof-process))
X		(interrupt-process proof-proc)
X		(sit-for 1)
X		(delete-process proof-proc))
X	    (error nil))
X	(error "One proof process at a time.")))
X  (setq proof-tmp-file (concat "/tmp/" (make-temp-name "#p#")))
X  (save-excursion
X    (setq proof-file (buffer-name))
X    (setq proof-buffer "*proof*")
X    (get-buffer-create proof-buffer)
X    (set-buffer proof-buffer)
X    (erase-buffer))
X  (write-region start end proof-tmp-file nil 'nomsg)
X  (setq proof-command 
X	(if (string= formatter "troff") 
X	    (format "troff -a %s %s %s" troff-options
X		    roff-macro proof-tmp-file)
X	  (format "nroff %s %s %s" nroff-options roff-macro proof-tmp-file)))
X (setq proof-process
X       (start-process formatter proof-buffer "sh" "-c" proof-command))
X (set-process-sentinel proof-process 'proof-sentinel))
X
X(defun proof-sentinel (process msg)
X  (delete-file proof-tmp-file)
X  (if (string-match "^exited" msg)
X      (message "%s: killed" (process-name process))
X    (progn
X      (set-buffer (process-buffer process))
X      (text-mode)
X      (setq mode-name (format "%s:%s"
X			      (process-name proof-process) proof-file))
X      (if (string= (process-name process) "nroff")
X	  (zap-nroff-crap))
X      (goto-char (point-min))
X      (display-buffer (process-buffer process))))
X  (setq proof-process nil))
X	
X(defun zap-nroff-crap ()
X  (goto-char (point-min))
X  (while (search-forward "\b" nil t)
X    (let* ((preceding (char-after (- (point) 2)))
X	   (following (following-char)))
X      	    ;; x\bx
X      (cond ((= preceding following)	
X	     (delete-char -2))
X	    ;; _\b
X	    ((= preceding ?\_)		
X	     (delete-char -2))
X	    ;; \b_
X	    ((= following ?\_)		
X	     (delete-region (1- (point)) (1+ (point)))))))
X  ;; expand ^G lines
X  (goto-char (point-min))
X  (while (search-forward "\C-g" nil t)	
X    (delete-char -2)
X    (while (not (eolp))
X      (insert " ")
X      (forward-char 1)))
X  ;; zap Esc-8 & Esc-9 vertical motions
X  (goto-char (point-min))
X  (while (search-forward "\e" nil t)
X    (if (or (= (following-char) ?8) (= (following-char) ?9))
X	    (delete-region (1+ (point)) (1- (point))))))
X
X
X
X
SHAR_EOF
if test 7181 -ne "`wc -c < 'format.el'`"
then
	echo shar: "error transmitting 'format.el'" '(should have been 7181 characters)'
fi
fi
exit 0
#	End of shell archive
__

Ronald Florence			...{hsi,rayssd}!mlfarm!ron