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