#!/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 $