#!/usr/bin/env ruby =begin rdoc == vpp - View and (selectively) Print PDF and PostScript === Synopsis vpp [options] [file] Options: -b, --batch=STRING run in batch using STRING for print command -p, --printer=STRING print to printer named STRING -d, --doublesided printer is doublesided -r, --rc=STRING use STRING as an rc file -V, --version print version and exit -v, --[no-]verbose be [not] verbose (quiet is the default) --[no-]view do [not] view the document --[no-]print do [not] offer printing interaction -h, --help print this help and exit === Copyright Copyright (C) 2009 Wybo Dekker (wybo@servalys.nl) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses. === Introduction _vpp_ displays a PDF or PostScript document (after conversion to PDF) using _xpdf_, _gv_, or any other PDF viewer of your choice). The user can use the viewer to print the document or, alternatively, leave the viewer and use _vpp_'s facilities to print selected pages to a one- or two-sided hardcopy or an A5-booklet: see the section `Page selection' for the details. Instead of printing your selections, you can also save them into PDF files. If +file+ is specified with a .ps or a .pdf extension, _vpp_ will simply use that +file+. Otherwise, _vpp_ will look for file.pdf, file.ps, and +file+, in that order, and will use the first existing file. If +file+ lacks, standard input is used. In any case, the first few characters in the file determine whether it is treated as a PDF or as a PostScript file. _vpp_ has three possible exit values: 0:: OK 1:: error 2:: edit, which is a signal to the calling program that a new edit session is at order; this is used by _mk_. 3:: re-compile; this is used by _mk_ === Options _vpp_ comes with several options. Before evaluating any options, _vpp_ will try to read a system rc-file, a user rc-file, and, finally an rc-file in the current directory. You can also set option defaults in an alias. For example: alias vpp='vpp --verbose' --help:: Prints help information, then quits --version:: Prints version, then quits. --verbose:: Prints messages about the progress _vpp_ is making. Can be reverted with --no-verbose --rc=rc-file:: Read specified rc-file before processing, but after any other rc files. The contents of this rc-file will override other options specified. --batch=string:: Prevents the --print option to interrogate the user about pages to be printed. Instead the document is printed according to the mandatory string. Also sets viewing off. Thus the command vpp -batch '2-3 x3' test.pdf prints 3 copies of pages 2 and 3 of test.pdf without viewing. --print:: Present the print prompt. This is the default. Can be reverted with --no-print, normally used to suppress the print prompt, for example when using _vpp_ from other scripts that generate PDF or PostScript documents that have only to be displayed or printed without even being displayed. --view:: Run the file viewer. This is the default. Can be reverted with --no-view, normally used to suppress starting the viewer, for example when using _vpp_ from other scripts that generate PDF or PostScript documents that have only to be printed. --printer=string:: Specifies the printer to be used instead of the system default printer. --doublesided:: Tells that the printer is able, and configured, to do doublesided printing. === Page selection When you select the --print option, and you did not also use the --batch option, _vpp_ interrogates you about the pages you want to print. To that end the following prompt appears: vpp command (? for help): upon typing ? or +h+, _vpp_ displays examples of possible commands: ===== Examples of print commands: 5 to print page 5 5- to print pages 5 through the end 5-7 to print pages 5, 6 and 7 -7 to print the first 7 pages 5-7,19- to print pages 5, 6, 7 and 19 through the end a to print the whole document - to print the whole document a x3 to print 3 copies of the document x3 the same 5 x3 to print 3 copies of page 5 t print the whole document twosided t 2- print twosided starting at page 2 b to print the whole document as an a5 size booklet b -12 to print the first 12 pages as an a5 size booklet Other commands: e (if called by mk) edit the tex source and rerun mk c (if called by mk) rerun mk v (re)view the ps/pdf file oxyz send pdf output to file xyz.pdf instead of printer h display this help ? display this help q quit ===== With these descriptions, no further explanation should be necessary, except for the following: When twosided (+t+) or booklet (+b+) printing is selected, printing will be performed in two shifts, one for the front side and one for the backside. Between the shifts, another prompt appears: printer ready? then turn stack and type return You will have to arrange your printer such that, with the printed sides up, the first page printed will be at the bottom of the stack, and the last page printed will be on top. Normally you will then have your output come out the back of your printer. `Turn the stack' then means: rotate it over the long side of the paper and feed it back into the printer for the other side to be printed. When you use the +oxyz+ subcommand, your selection will not be printed but instead will be saved in a PDF file named xyz.pdf. When you use a +t+ or +b+ selection, you will not, of course, be prompted to turn the paper stack. Instead, the odd and even pages of your selection will be saved in separate PDF files, xyz_odd.pdf and xyz_even.pdf. === RC-files and customization Unless the environment variable NORC has been set, three rc-files are executed, if they exist, before reading the command line options, in the following order: /etc/vpprc:: the system rc-file $HOME/.vpprc:: the user rc-file ./.vpprc:: the local rc-file You can use these rc-files to set the default values for some of the options, by quoting key = value pairs. Valid keys are: @batch:: (string) sets the --batch option @print:: (true or false) sets printing interaction on of off @printer:: (string) sets the --printer option @doublesided:: (true or false) sets the --doublesided option @verbose:: (true or false) sets the --verbose option @view:: (true or false) sets viewing on or off @viewer:: (string) set the viewer; arguments may be added For example: @verbose = true # run in verbose mode set your PDF viewer: @viewer = 'gv' # set the viewer You should use a basename here, i.e. the name of the viewer should contain no slashes, and it should be in your PATH. But you may add options, for example: @viewer = 'acroread -geometry 1450x1150+0+0' _xpdf_ is the default viewer for both PostScript and PDF; PostScript files are temporarily converted to PDF for viewing. You may add Ruby-style comments as usual in rc files, but rdoc-style comments are not allowed. === Examples Since _vpp_ can read from standard input, it can be used to print (parts of) manpages. This example prints the full +ls+ manpage first, followed by an A5 booklet of the first 8 pages: $ man -t ls | vpp # (xpdf shows preview and is left with `q') vpp command (? for help): a vpp command (? for help): b 1-8 printer ready? then turn pack over the long side and type enter (^D skips) vpp command (? for help): q $ If you don't need a preview, because you have seen the man page already, you can print it immediately as an A5 booklet with: $ man -t ls | vpp --batch=b or, to make an A5 booklet of the first 8 pages: $ man -t ls |vpp --batch='-8 b' If you just want to save a PDF copy of the man page, you can say: $ man -t ls |vpp -b ols Some PDF-documents, like the CVS manual (cvs.pdf), have their Table of Contents in their back instead of behind the title page. You can use vpp to rearrange such documents: $ vpp --batch='1,2,153-160,3-152 ocvs' cvs.pdf This overwrites the input document. Note that any links in the file will get broken, so that is only useful for documents that have to be printed. It would have been more sensible in this case to say: $ vpp --batch=b 1,2,153-160,3-152' cvs which prints the reordered document as an A5 booklet without replacing it. You can even print or output page ranges in reverse order: $ vpp --batch='12-1 otest' cvs.pdf =end require 'readline' include Readline require 'fileutils' include FileUtils begin require 'scriptingutils' rescue LoadError raise LoadError,< -#3 lpropt = "-#"+$1 when /^o(.*)/: # output to file instead of printer output = $1.sub(/\~/,ENV['HOME']) if output == '' puts("filename must follow o without spacing") return 'continue' end if output =~ /\// puts("filename may not contain /'s") return 'continue' end @saved = true when 'b': booklet = true # print a5 booklet when 't': twosided = true # print twosided when 'a': selection = '-' # print all when '-': selection = '-' # print all when /^((\d+-?\d*|\d*-?\d+),?)+$/: # n-m or n- or -m selection = c.sub(/,$/,'') when /^(\?|h)$/: puts input_options return 'continue' else puts "Illegal specification(s)" puts input_options return 'continue' end end # pages in range? selection.sub!(/^-/,'1-') # -m means 1-m selection.sub!(/-$/,"-#{@pagecount}") # n- means n-@pagecount selection.split(/\D+/).each do |n| unless n.to_i.between?(1,@pagecount) puts "Illegal page number #{n}; PDF has #{@pagecount} pages" return 'continue' end end return selection,booklet,twosided,lpropt,output end # print selected pages def printout # always get commands interactively if Readline.respond_to?('input') # for ruby versions > 1.8.2 Readline.input = open(DEVTTY) else # for ruby versions upto 1.8.2 STDIN.reopen DEVTTY unless STDIN.tty? end loop do selection,booklet,twosided,lpropt,output = ask_selection(@batch) selection == 'quit' and quit selection == 'continue' and next selection ||= '-' if output output.sub!(/.*\//,'') output = File.join(ENV['VPPOUTDIR'] || WORKDIR,output) end if @doublesided doselection(selection,booklet, nil ,lpropt,output) else if booklet doselection(selection,true, 'odd' ,lpropt,output) wait_for_printer unless output doselection(selection,true, 'even',lpropt,output) elsif twosided doselection(selection,false,'odd' ,lpropt,output) wait_for_printer unless output doselection(selection,false,'even',lpropt,output) else doselection(selection,false, nil ,lpropt,output) end end break if @batch end end # return the input options, taken from the rdoc comment: def input_options sep = "\n=====\n" open(MYABSNAME) do |f| "\n" + f.readlines(sep)[1].chomp(sep) + "\n" end end init(NEEDED,:handle_options) find_viewer @filename = pdf @width, @height, @pagecount = pdfproperties(@filename) @view || @print or quit("Nothing to do: use --view or --print or both",1) @view and view(@viewer,@filename) @print and printout quit # $Id: vpp,v 1.69 2009-11-11 14:44:01 wybo Exp $