11package cmd
22
33import (
4+ "errors"
45 "fmt"
56 "io"
67 "os"
8+ "strings"
79
810 "github.com/klippa-app/go-pdfium/requests"
911
1012 "github.com/klippa-app/pdfium-cli/pdf"
1113 "github.com/spf13/cobra"
1214)
1315
16+ // parseFileWithPageRange parses a file argument that may contain an optional page range
17+ // in the format "filename.pdf[1-3]". Returns the filename and page range string.
18+ // If no page range is specified, returns "first-last" as the page range.
19+ func parseFileWithPageRange (arg string ) (string , string ) {
20+ if strings .HasSuffix (arg , "]" ) {
21+ bracketIdx := strings .LastIndex (arg , "[" )
22+ if bracketIdx != - 1 {
23+ pageRange := arg [bracketIdx + 1 : len (arg )- 1 ]
24+ if pageRange != "" {
25+ return arg [:bracketIdx ], pageRange
26+ }
27+ }
28+ }
29+ return arg , "first-last"
30+ }
31+
1432func init () {
1533 addGenericPDFOptions (mergeCmd )
34+ addIgnoreInvalidPagesOption (mergeCmd )
1635 rootCmd .AddCommand (mergeCmd )
1736}
1837
1938var mergeCmd = & cobra.Command {
20- Use : "merge [input] [input] ([input]...) [output]" ,
39+ Use : "merge [input] ([input]...) [output]" ,
2140 Short : "Merge multiple PDFs into a single PDF" ,
22- Long : "Merge multiple PDFs into a single PDF.\n [output] can either be a file path or - for stdout." ,
41+ Long : "Merge multiple PDFs into a single PDF.\n [output] can either be a file path or - for stdout.\n Each [input] can optionally include a page range using the syntax filename.pdf[{pagerange}], \n for example invoice.pdf[1-3] to include only pages 1, 2 and 3. " ,
2342 Args : func (cmd * cobra.Command , args []string ) error {
43+ if len (args ) < 1 {
44+ return newExitCodeError (errors .New ("no input given" ), ExitCodeInvalidArguments )
45+ }
2446 if args [0 ] == stdFilename {
25- if err := cobra .MinimumNArgs (2 )(cmd , args ); err != nil {
47+ if err := cobra .MinimumNArgs (1 )(cmd , args ); err != nil {
2648 return newExitCodeError (err , ExitCodeInvalidArguments )
2749 }
2850 } else {
29- if err := cobra .MinimumNArgs (3 )(cmd , args ); err != nil {
51+ if err := cobra .MinimumNArgs (2 )(cmd , args ); err != nil {
3052 return newExitCodeError (err , ExitCodeInvalidArguments )
3153 }
3254
3355 for i := 0 ; i < len (args )- 1 ; i ++ {
34- if _ , err := os .Stat (args [i ]); err != nil {
35- return fmt .Errorf ("could not open input file %s: %w" , args [0 ], newExitCodeError (err , ExitCodeInvalidInput ))
56+ filename , _ := parseFileWithPageRange (args [i ])
57+ if _ , err := os .Stat (filename ); err != nil {
58+ return fmt .Errorf ("could not open input file %s: %w" , filename , newExitCodeError (err , ExitCodeInvalidInput ))
3659 }
3760 }
3861 }
@@ -57,14 +80,16 @@ var mergeCmd = &cobra.Command{
5780 i := 0
5881 for true {
5982 var filename string
83+ var filePageRange string
6084 if args [0 ] == stdFilename {
6185 filename = stdFilename
86+ filePageRange = "first-last"
6287 } else {
6388 // Reached last file.
6489 if i == len (args )- 1 {
6590 break
6691 }
67- filename = args [i ]
92+ filename , filePageRange = parseFileWithPageRange ( args [i ])
6893 }
6994
7095 document , closeFile , err := openFile (filename )
@@ -73,7 +98,7 @@ var mergeCmd = &cobra.Command{
7398 if err == stdinNoMoreFiles {
7499 break
75100 }
76- handleError (cmd , fmt .Errorf ("could not open input file %s: %w\n " , args [ i ] , err ), ExitCodeInvalidInput )
101+ handleError (cmd , fmt .Errorf ("could not open input file %s: %w\n " , filename , err ), ExitCodeInvalidInput )
77102 return
78103 }
79104
@@ -86,14 +111,14 @@ var mergeCmd = &cobra.Command{
86111 })
87112 if err != nil {
88113 closeFunc ()
89- handleError (cmd , fmt .Errorf ("could not get page ranges for file %s: %w" , args [ i ] , newPdfiumError (err )), ExitCodePdfiumError )
114+ handleError (cmd , fmt .Errorf ("could not get page ranges for file %s: %w" , filename , newPdfiumError (err )), ExitCodePdfiumError )
90115 return
91116 }
92117
93- pageRange , calculatedPageCount , err := pdf .NormalizePageRange (pageCount .PageCount , "first-last" , false )
118+ pageRange , calculatedPageCount , err := pdf .NormalizePageRange (pageCount .PageCount , filePageRange , ignoreInvalidPages )
94119 if err != nil {
95120 closeFunc ()
96- handleError (cmd , fmt .Errorf ("invalid page range 'first-last' : %w\n " , err ), ExitCodeInvalidPageRange )
121+ handleError (cmd , fmt .Errorf ("invalid page range '%s' for file %s : %w\n " , filePageRange , filename , err ), ExitCodeInvalidPageRange )
97122 return
98123 }
99124
@@ -105,7 +130,7 @@ var mergeCmd = &cobra.Command{
105130 })
106131 if err != nil {
107132 closeFunc ()
108- handleError (cmd , fmt .Errorf ("could not import pages for file %s: %w" , args [ i ] , newPdfiumError (err )), ExitCodePdfiumError )
133+ handleError (cmd , fmt .Errorf ("could not import pages for file %s: %w" , filename , newPdfiumError (err )), ExitCodePdfiumError )
109134 return
110135 }
111136
@@ -116,7 +141,7 @@ var mergeCmd = &cobra.Command{
116141 })
117142 if err != nil {
118143 closeFunc ()
119- handleError (cmd , fmt .Errorf ("could not close document for file %s: %w" , args [ i ] , newPdfiumError (err )), ExitCodePdfiumError )
144+ handleError (cmd , fmt .Errorf ("could not close document for file %s: %w" , filename , newPdfiumError (err )), ExitCodePdfiumError )
120145 return
121146 }
122147
0 commit comments