#!/bin/sh : ; exec klone $0 "$@" ; The above line finds the klone executable in the $PATH ;;; list of printers: p-list name and ;;; (reverse? x-offset y-offset space-between-colums use_-h) ;;; defaults is for the () printer (setq printers '( nwcroap (t 600 100 380 ()) lwcroap (() 650 -500 380 ()) () (() 650 0 380 t) )) ;;; options (setq files (getopts "lpt [options] files... - print text files on a postscript printer uses enscript to get a prettyfied output. ~/.lpt-printers can be defined to hold printer descriptions in lisp, as lines written as: printer-name (reverse? x-offset y-offset separation use-h?) where flags are t or () and numbers in points - reverse? is t if pages must be printed lasr first - x-offset and y-offset are horizontal and vertical margins - separation is the magin between columns (recommended: 380) - use-h? if t then lpr -h is used, lpr alone otherwise to send to printer for instance: nwcroap (t 600 100 380 ()) lwcroap (() 650 0 380 t)" ("-P" printer printer-name "printer on which to print") ("-r" () reverse "reverse the pages") ("-n" () no-print "do not send postscript to printer but to stdout") ("-g" () garbage "prints file even if it contains lots of non-ASCII chars") ("-c" number (columns 2) "prints in \"number\" columns (defaults to 2)") ("-l" number (lines 66) "number of lines per page (default 66)") ("-w" () wrap-lines "wraps wide lines (default is to truncate)") ("-a" () print-name-on-all "prints user name and date on all pages (default only on first)") ("-T" () test-file "prints a test page for calibrating on new printers") ("-v" () verbose "verbose") )) (setq enscript-command '( "enscript" "-2r" "-k" "-L66" "-FHelvetica-Bold7" "-fCourier7" "-p" )) (setq print-command '( "lpr" )) (setq user-printers (list)) (if (setq fd (open "~/.lpt-printers" :error ())) (progn (while (setq item (read fd ())) (lappend user-printers item) ) (setq printers (+ user-printers printers)) )) (setq second-column-start 7920) (defun main () (if (typep columns String) (progn (setq columns (Int columns)) (put enscript-command 1 (+ "-" (String columns) "r"))) ) (if (/= lines 66) (progn (setq lines (+ "-L" (String lines))) (with (pos (seek enscript-command "-L66")) (put enscript-command pos lines) ))) (if (not wrap-lines) (insert enscript-command 1 "-c")) (if test-file (with (fd (open "/tmp/lpt_test" :direction :output :if-exists :supersede )) (print-test-file fd) (close fd) (setq files (list "/tmp/lpt_test")) )) (setq temp-file (+ "/tmp/lpt" (String *current-process-id*))) (dolist (file files) (nconc temp-file ",_" (match "(.*[/]|^)(.*)$" file 2))) (if (> (length temp-file) 80) (setq temp-file (subseq temp-file 0 79))) (nconc enscript-command (list temp-file)) (if garbage (nconc enscript-command (list "-g"))) (dolist (file files) (nconc enscript-command (list file))) (if (not printer-name) (if (getenv "PRINTER") (setq printer-name (getenv "PRINTER"))) ) (if printer-name (nconc print-command (list (+ "-P" printer-name)))) (nconc print-command (list temp-file)) (setq printer-props (get printers printer-name '(get printers () '(() 0 0)))) (if (getn printer-props 0) (setq reverse (not reverse))) (setq offsets (subseq printer-props 1 3)) (setq space-between-columns (get printer-props 3 380)) (if (getn printer-props 4) (insert print-command 1 "-h")) ;;; do enscript (if (/= 0 (setq code (wait (system enscript-command)))) (progn (print-format *standard-error* "lpt: enscript error (code %0), nothing sent!\n" code ) (exit 1) )) ;;; post-process file (setq fd (open temp-file)) (file-position fd 0) (setq re-header-font (regcomp "^[0-9]+ [0-9]+ [/]Helvetica-Bold$")) (setq re-body-font (regcomp "^[0-9]+ [0-9]+ [/]Courier$")) (setq re-offset (regcomp "^([/]Landscape *[{] *90 +rotate +)(-?[0-9]+) +(-?[0-9]+)( +translate[}] *def)$" )) (setq re-endprolog (regcomp "^[%][%]EndProlog$")) (setq re-fontdict-decl (regcomp "^2 SetUpFonts$")) (setq lines (list)) ;;; treat prolog (setq prolog t) (while (and prolog (setq line (read-line fd ()))) (if (regexec re-header-font line) (progn (lappend lines "2 250 /Helvetica-Bold\n1 400 /Helvetica-Bold") ) (regexec re-body-font line) (progn (lappend lines "0 160 /Courier") ;bigger (8pt) body font ) (regexec re-fontdict-decl line) (progn (lappend lines "3 SetUpFonts") ) (regexec re-offset line) (progn (setq x-offset (Int (regsub re-offset 2))) (setq y-offset (Int (regsub re-offset 3))) (incf x-offset (get offsets 0)) (incf y-offset (get offsets 1)) (lappend lines (+ (regsub re-offset 1) (String x-offset) " " (String y-offset) (regsub re-offset 4) ))) (regexec re-endprolog line) (progn (lappend lines line) (setq prolog ()) ) (lappend lines line) )) ;;; treat body (setq re-header-decl (regcomp "^1 F$")) (setq re-second-column (regcomp (+ "^([0-9]+) +( .*[)]B)$"))) (with (pos 0) (catch 'EOF (while t (setq line (read-line fd)) (if (and (regexec re-second-column line) (>= (setq pos (Int (regsub re-second-column 1))) second-column-start )) (lappend lines (+ (String (+ space-between-columns pos)) (regsub re-second-column 1) )) (regexec re-header-decl line) (progn (lappend lines line) (lappend lines (process-header (read-line fd ()))) ) (lappend lines line) )))) (close fd) (setq fd (open temp-file :direction :output :if-exists :supersede)) (dolist (line lines) (write-line line fd)) (close fd) ;;; reverse? (if reverse (progn (setq system-command (+ "mv " temp-file " " temp-file ".bak; " "pstops -q -0 < " temp-file ".bak > " temp-file "; " "rm -f " temp-file ".bak; " )) (wait (system system-command)) )) ;;; print (if no-print (wait (system (list "cat" temp-file))) (wait (system print-command)) ) ;;; clean (wait (system (list "rm" "-f" temp-file))) ) (setq ps-quotable-chars "()\\") (setq re-ps-quotable (regcomp (+ "[" ps-quotable-chars "]"))) (defun postscript-quote (s &aux res) (if (regexec re-ps-quotable s) (progn (setq res (copy "")) (dolist (c s) (if (seek ps-quotable-chars c) (put res -1 #\\) ) (put res -1 c) ) ) s )) ;;; treat page header (setq re-header (regcomp "^[0-9]+ [0-9]+ [(]([^ ]+)[ ]+([^ ].*[^ ])[ ]+([0-9]+)[)]B$" )) (and (not (setq username (getenv "NAME"))) (not (setq username (getenv "USER"))) (setq username "") ) (setq username (postscript-quote username)) (defun process-header (line &aux (res (Stream "")) ) (if (regexec re-header line) (with ( name (relative-name (regsub re-header 1)) date (regsub re-header 2) page (regsub re-header 3) ) (print-format res "360 15000 (%0)B\n" (postscript-quote name)) (print-format res "15000 15000 (%0)B\n" page) (if (or print-name-on-all (= "1" page)) (print-format res "2 F\n10000 15000 (%0)B\n10000 15250 (%1)B" (postscript-quote date) username) ) (String res) ) line ;unrecognized? ) ) (setq homedir (expand-filename "~")) (setq homedir-len (length homedir)) (defun relative-name (name) (if (= (subseq name 0 homedir-len) homedir) (+ "~" (subseq name homedir-len)) name ) ) ;; prints a test page (2 x 66 lines of 80 chars) on fd (defun print-test-file (fd) (dotimes (i 132) (print-format fd "#[%0]# " (expand-num i 3 :filler #\ )) (dotimes (j 7) (print-format fd ".%00 56789" (+ 1 j))) (print-format fd "\n") )) (main) ;;; EMACS MODES ;;; Local Variables: *** ;;; mode:lisp *** ;;; End: ***