Skip to content

Commit 125cee2

Browse files
committed
Fix #716, add option for merging with divider
1 parent 4f99328 commit 125cee2

File tree

17 files changed

+642
-200
lines changed

17 files changed

+642
-200
lines changed

Dockerfile

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,23 @@
11
# Dockerfile References: https://docs.docker.com/engine/reference/builder/
2+
#
3+
# Usage:
4+
#
5+
# docker build -t pdfcpu .
6+
#
7+
# Simple one off container:
8+
# docker run pdfcpu
9+
#
10+
# One off container with dir binding:
11+
# docker run -v $(pwd):/data -it --rm pdfcpu pdfcpu val test.pdf
12+
#
13+
# Create & run reusable container with dir binding:
14+
# docker run --name pdfcpu -v $(pwd):/data -it pdfcpu /bin/sh
15+
# /data # ... // run pdfcpu commands against your data
16+
# /data # exit // exit container
17+
#
18+
# docker start -i pdfcpu // restart container with dir binding
19+
# /data # ... // run pdfcpu commands against your data
20+
# /data # exit // exit container
221

322
# Start from the latest golang base image
423
FROM golang:latest as builder
@@ -10,12 +29,19 @@ RUN go install github.com/pdfcpu/pdfcpu/cmd/pdfcpu@latest
1029

1130
FROM alpine:latest
1231

13-
RUN apk --no-cache add ca-certificates
32+
RUN apk --no-cache add ca-certificates gcompat
1433

15-
WORKDIR /root/
34+
WORKDIR /root
35+
36+
# Copy the pre-built binary file from the previous stage
37+
COPY --from=builder /go/bin ./
38+
39+
# Export path of executable
40+
ENV PATH="${PATH}:/root"
41+
42+
WORKDIR /data
43+
44+
# Command to run executable
45+
CMD pdfcpu && echo && pdfcpu version -v
1646

17-
# Copy the Pre-built binary file from the previous stage
18-
COPY --from=builder /go/bin .
1947

20-
# Command to run the executable
21-
CMD ["./pdfcpu"]

c1.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mode: set

cmd/pdfcpu/init.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ func initCommandMap() {
303303
}
304304

305305
func initFlags() {
306+
flag.BoolVar(&all, "all", false, "")
307+
flag.BoolVar(&all, "a", false, "")
306308

307309
bookmarksUsage := "create bookmarks while merging"
308310
flag.BoolVar(&bookmarks, "bookmarks", true, bookmarksUsage)
@@ -313,6 +315,10 @@ func initFlags() {
313315
flag.StringVar(&conf, "conf", "", confUsage)
314316
flag.StringVar(&conf, "c", "", confUsage)
315317

318+
dividerPageUsage := "create divider pages while merging"
319+
flag.BoolVar(&dividerPage, "dividerPage", false, dividerPageUsage)
320+
flag.BoolVar(&dividerPage, "d", false, dividerPageUsage)
321+
316322
jsonUsage := "produce JSON output"
317323
flag.BoolVar(&json, "json", false, jsonUsage)
318324
flag.BoolVar(&json, "j", false, jsonUsage)
@@ -354,15 +360,12 @@ func initFlags() {
354360
flag.StringVar(&unit, "unit", "", unitUsage)
355361
flag.StringVar(&unit, "u", "", unitUsage)
356362

357-
flag.BoolVar(&verbose, "verbose", false, "")
358-
flag.BoolVar(&verbose, "v", false, "")
359-
flag.BoolVar(&veryVerbose, "vv", false, "")
360-
361363
flag.StringVar(&upw, "upw", "", "user password")
362364
flag.StringVar(&opw, "opw", "", "owner password")
363365

364-
flag.BoolVar(&all, "all", false, "")
365-
flag.BoolVar(&all, "a", false, "")
366+
flag.BoolVar(&verbose, "verbose", false, "")
367+
flag.BoolVar(&verbose, "v", false, "")
368+
flag.BoolVar(&veryVerbose, "vv", false, "")
366369
}
367370

368371
func initLogging(verbose, veryVerbose bool) {

cmd/pdfcpu/main.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ import (
2323
)
2424

2525
var (
26-
fileStats, mode, selectedPages string
27-
upw, opw, key, perm, unit, conf string
28-
verbose, veryVerbose bool
29-
links, quiet, sorted, bookmarks bool
30-
all, json, replaceBookmarks bool
31-
needStackTrace = true
32-
cmdMap commandMap
26+
fileStats, mode, selectedPages string
27+
upw, opw, key, perm, unit, conf string
28+
verbose, veryVerbose bool
29+
links, quiet, sorted, bookmarks bool
30+
all, dividerPage, json, replaceBookmarks bool
31+
needStackTrace = true
32+
cmdMap commandMap
3333
)
3434

3535
// Set by Goreleaser.

cmd/pdfcpu/process.go

Lines changed: 59 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import (
2424
"os"
2525
"path/filepath"
2626
"regexp"
27+
"runtime"
28+
"runtime/debug"
2729
"sort"
2830
"strconv"
2931
"strings"
@@ -123,13 +125,24 @@ func printVersion(conf *model.Configuration) {
123125
os.Exit(1)
124126
}
125127

126-
fmt.Fprintf(os.Stdout, "pdfcpu: %v\n", model.VersionStr)
127-
if date != "?" {
128-
fmt.Fprintf(os.Stdout, "build : %v\ncommit: %v\n", date, commit)
129-
}
130-
if verbose {
131-
fmt.Fprintf(os.Stdout, "config: %s\n", conf.Path)
128+
fmt.Fprintf(os.Stdout, "pdfcpu: %s\n", model.VersionStr)
129+
130+
if date == "?" {
131+
if info, ok := debug.ReadBuildInfo(); ok {
132+
for _, setting := range info.Settings {
133+
if setting.Key == "vcs.revision" {
134+
commit = setting.Value
135+
}
136+
if setting.Key == "vcs.time" {
137+
date = setting.Value
138+
}
139+
}
140+
}
132141
}
142+
143+
fmt.Fprintf(os.Stdout, "commit: %s (%s)\n", commit[:8], date)
144+
fmt.Fprintf(os.Stdout, "base : %s\n", runtime.Version())
145+
fmt.Fprintf(os.Stdout, "config: %s\n", conf.Path)
133146
}
134147

135148
func process(cmd *cli.Command) {
@@ -247,7 +260,7 @@ func processSplitCommand(conf *model.Configuration) {
247260
if mode == "" {
248261
mode = "span"
249262
}
250-
mode = extractModeCompletion(mode, []string{"span", "bookmark", "page"})
263+
mode = modeCompletion(mode, []string{"span", "bookmark", "page"})
251264
if mode == "" || len(flag.Args()) < 2 || selectedPages != "" {
252265
fmt.Fprintf(os.Stderr, "%s\n\n", usageSplit)
253266
os.Exit(1)
@@ -302,21 +315,7 @@ func sortFiles(filesIn []string) {
302315
})
303316
}
304317

305-
func processMergeCommand(conf *model.Configuration) {
306-
if mode == "" {
307-
mode = "create"
308-
}
309-
mode = extractModeCompletion(mode, []string{"create", "append"})
310-
if mode == "" {
311-
fmt.Fprintf(os.Stderr, "%s\n\n", usageMerge)
312-
os.Exit(1)
313-
}
314-
315-
if len(flag.Args()) < 2 || selectedPages != "" {
316-
fmt.Fprintf(os.Stderr, "%s\n\n", usageMerge)
317-
os.Exit(1)
318-
}
319-
318+
func processArgsForMerge(conf *model.Configuration) ([]string, string) {
320319
filesIn := []string{}
321320
outFile := ""
322321
for i, arg := range flag.Args() {
@@ -329,7 +328,7 @@ func processMergeCommand(conf *model.Configuration) {
329328
fmt.Fprintf(os.Stderr, "%s may appear as inFile or outFile only\n", outFile)
330329
os.Exit(1)
331330
}
332-
if strings.Contains(arg, "*") {
331+
if mode != "zip" && strings.Contains(arg, "*") {
333332
matches, err := filepath.Glob(arg)
334333
if err != nil {
335334
fmt.Fprintf(os.Stderr, "%s", err)
@@ -343,6 +342,34 @@ func processMergeCommand(conf *model.Configuration) {
343342
}
344343
filesIn = append(filesIn, arg)
345344
}
345+
return filesIn, outFile
346+
}
347+
348+
func processMergeCommand(conf *model.Configuration) {
349+
if mode == "" {
350+
mode = "create"
351+
}
352+
mode = modeCompletion(mode, []string{"create", "append", "zip"})
353+
if mode == "" {
354+
fmt.Fprintf(os.Stderr, "%s\n\n", usageMerge)
355+
os.Exit(1)
356+
}
357+
358+
if len(flag.Args()) < 2 || selectedPages != "" {
359+
fmt.Fprintf(os.Stderr, "%s\n\n", usageMerge)
360+
os.Exit(1)
361+
}
362+
363+
if mode == "zip" && len(flag.Args()) != 3 {
364+
fmt.Fprintf(os.Stderr, "merge zip: expecting outFile inFile1 inFile2\n")
365+
os.Exit(1)
366+
}
367+
368+
if mode == "zip" && dividerPage {
369+
fmt.Fprintf(os.Stderr, "merge zip: -d(ivider) not applicable and will be ignored\n")
370+
}
371+
372+
filesIn, outFile := processArgsForMerge(conf)
346373

347374
if sorted {
348375
sortFiles(filesIn)
@@ -360,16 +387,20 @@ func processMergeCommand(conf *model.Configuration) {
360387
switch mode {
361388

362389
case "create":
363-
cmd = cli.MergeCreateCommand(filesIn, outFile, conf)
390+
cmd = cli.MergeCreateCommand(filesIn, outFile, dividerPage, conf)
391+
392+
case "zip":
393+
cmd = cli.MergeCreateZipCommand(filesIn, outFile, conf)
364394

365395
case "append":
366-
cmd = cli.MergeAppendCommand(filesIn, outFile, conf)
396+
cmd = cli.MergeAppendCommand(filesIn, outFile, dividerPage, conf)
397+
367398
}
368399

369400
process(cmd)
370401
}
371402

372-
func extractModeCompletion(modePrefix string, modes []string) string {
403+
func modeCompletion(modePrefix string, modes []string) string {
373404
var modeStr string
374405
for _, mode := range modes {
375406
if !strings.HasPrefix(mode, modePrefix) {
@@ -384,7 +415,7 @@ func extractModeCompletion(modePrefix string, modes []string) string {
384415
}
385416

386417
func processExtractCommand(conf *model.Configuration) {
387-
mode = extractModeCompletion(mode, []string{"image", "font", "page", "content", "meta"})
418+
mode = modeCompletion(mode, []string{"image", "font", "page", "content", "meta"})
388419
if len(flag.Args()) != 2 || mode == "" {
389420
fmt.Fprintf(os.Stderr, "%s\n\n", usageExtract)
390421
os.Exit(1)
@@ -2061,7 +2092,7 @@ func processMultiFillFormCommand(conf *model.Configuration) {
20612092
if mode == "" {
20622093
mode = "single"
20632094
}
2064-
mode = extractModeCompletion(mode, []string{"single", "merge"})
2095+
mode = modeCompletion(mode, []string{"single", "merge"})
20652096
if mode == "" {
20662097
fmt.Fprintf(os.Stderr, "usage: %s\n\n", usageFormMultiFill)
20672098
os.Exit(1)

cmd/pdfcpu/usage.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,13 @@ Eg. pdfcpu split test.pdf . (= pdfcpu split -m span test.pdf . 1)
153153
test_4-9.pdf
154154
test_10-20.pdf`
155155

156-
usageMerge = "usage: pdfcpu merge [-m(ode) create|append] [-s(ort) -b(ookmarks)] outFile inFile..." + generalFlags
156+
usageMerge = "usage: pdfcpu merge [-m(ode) create|append|zip] [ -s(ort) -b(ookmarks) -d(ivider)] outFile inFile..." + generalFlags
157157
usageLongMerge = `Concatenate a sequence of PDFs/inFiles into outFile.
158158
159159
mode ... merge mode (defaults to create)
160160
sort ... sort inFiles by file name
161161
bookmarks ... create bookmarks
162+
divider ... insert blank page between merged documents
162163
outFile ... output PDF file
163164
inFile ... a list of PDF files subject to concatenation.
164165
@@ -168,6 +169,8 @@ The merge modes are:
168169
169170
append ... if outFile does not exist, it will be created (like in default mode).
170171
if outFile already exists, inFiles will be appended to outFile.
172+
173+
zip ... zip inFile1 and inFile2 into outFile (which will be created and possibly overwritten).
171174
172175
Skip bookmark creation like so: -bookmarks=false`
173176

@@ -791,8 +794,8 @@ Examples: pdfcpu grid out.pdf 1 10 in.pdf
791794
Kiku4, Kiku5
792795
AB, B40, Shikisen`
793796

794-
usageVersion = "usage: pdfcpu version [-v(erbose)|vv]"
795-
usageLongVersion = "Print the pdfcpu version."
797+
usageVersion = "usage: pdfcpu version"
798+
usageLongVersion = "Print the pdfcpu version & build info."
796799

797800
usagePaper = "usage: pdfcpu paper"
798801
usageLongPaper = "Print a list of supported paper sizes."

pkg/api/example_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,15 @@ func ExampleMergeCreateFile() {
8484
// Merge inFiles by concatenation in the order specified and write the result to out.pdf.
8585
// out.pdf will be overwritten.
8686
inFiles := []string{"in1.pdf", "in2.pdf"}
87-
MergeCreateFile(inFiles, "out.pdf", nil)
87+
MergeCreateFile(inFiles, "out.pdf", false, nil)
8888
}
8989

9090
func ExampleMergeAppendFile() {
9191

9292
// Merge inFiles by concatenation in the order specified and write the result to out.pdf.
9393
// If out.pdf already exists it will be preserved and serves as the beginning of the merge result.
9494
inFiles := []string{"in1.pdf", "in2.pdf"}
95-
MergeAppendFile(inFiles, "out.pdf", nil)
95+
MergeAppendFile(inFiles, "out.pdf", false, nil)
9696
}
9797

9898
func ExampleInsertPagesFile() {

pkg/api/form.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ func parseFormGroup(rd io.Reader) (*form.FormGroup, error) {
629629

630630
func mergeForms(outDir, fileName string, outFiles []string, conf *model.Configuration) error {
631631
outFile := filepath.Join(outDir, fileName+".pdf")
632-
if err := MergeCreateFile(outFiles, outFile, conf); err != nil {
632+
if err := MergeCreateFile(outFiles, outFile, false, conf); err != nil {
633633
return err
634634
}
635635
if log.CLIEnabled() {

0 commit comments

Comments
 (0)