77 "errors"
88 "flag"
99 "fmt"
10- "io"
1110 "log"
1211 "os"
1312 "os/signal"
@@ -21,13 +20,21 @@ import (
2120
2221 "github.com/bool64/dev/version"
2322 "github.com/bool64/progress"
24- gzip "github.com/klauspost/pgzip"
2523)
2624
2725// Main is the entry point for catp CLI tool.
2826func Main (options ... func (o * Options )) error { //nolint:funlen,cyclop,gocognit,gocyclo,maintidx
2927 r := & runner {}
3028
29+ var closers []func () error
30+ defer func () {
31+ for _ , closer := range closers {
32+ if err := closer (); err != nil {
33+ log .Printf ("failed to close: %s\n " , err .Error ())
34+ }
35+ }
36+ }()
37+
3138 flag .Var (flagFunc (func (v string ) error {
3239 r .filters .addFilter (true , bytes .Split ([]byte (v ), []byte ("^" ))... )
3340
@@ -62,6 +69,17 @@ func Main(options ...func(o *Options)) error { //nolint:funlen,cyclop,gocognit,g
6269 "if filter matches, line is removed from the output (may be kept if it passed preceding -pass)\n " +
6370 "for example, you can use \" -skip quux^baz -skip fooO\" to skip lines that have (quux AND baz) OR fooO" )
6471
72+ flag .Var (flagFunc (func (v string ) error {
73+ w , closer , err := makeWriter (v )
74+ if err != nil {
75+ return err
76+ }
77+
78+ closers = append (closers , closer )
79+
80+ return r .filters .saveTo (w )
81+ }), "save-matches" , "save matches of previous filter group to file" )
82+
6583 flag .IntVar (& r .parallel , "parallel" , 1 , "number of parallel readers if multiple files are provided\n " +
6684 "lines from different files will go to output simultaneously (out of order of files, but in order of lines in each file)\n " +
6785 "use 0 for multi-threaded zst decoder (slightly faster at cost of more CPU)" )
@@ -85,7 +103,7 @@ func Main(options ...func(o *Options)) error { //nolint:funlen,cyclop,gocognit,g
85103 "default is 0 (no limit), each input file is counted separately" )
86104
87105 flag .Usage = func () {
88- fmt .Println ("catp" , version .Module ("github.com/bool64/progress" ).Version + "," ,
106+ fmt .Println ("catp" , version .Module ("github.com/bool64/progress" ).Version + r . options . VersionLabel + "," ,
89107 version .Info ().GoVersion , strings .Join (versionExtra , " " ))
90108 fmt .Println ()
91109 fmt .Println ("catp prints contents of files to STDOUT or dir/file output, \n " +
@@ -99,20 +117,6 @@ func Main(options ...func(o *Options)) error { //nolint:funlen,cyclop,gocognit,g
99117 }
100118 flag .Parse ()
101119
102- r .filters .buildIndex ()
103-
104- if * ver {
105- fmt .Println (version .Module ("github.com/bool64/progress" ).Version )
106-
107- return nil
108- }
109-
110- if flag .NArg () == 0 {
111- flag .Usage ()
112-
113- return nil
114- }
115-
116120 if * cpuProfile != "" {
117121 startProfiling (* cpuProfile , * memProfile )
118122
@@ -127,6 +131,20 @@ func Main(options ...func(o *Options)) error { //nolint:funlen,cyclop,gocognit,g
127131 }
128132 }
129133
134+ r .filters .buildIndex ()
135+
136+ if * ver {
137+ fmt .Println (version .Module ("github.com/bool64/progress" ).Version + r .options .VersionLabel )
138+
139+ return nil
140+ }
141+
142+ if flag .NArg () == 0 {
143+ flag .Usage ()
144+
145+ return nil
146+ }
147+
130148 var files []string
131149
132150 args := flag .Args ()
@@ -163,61 +181,21 @@ func Main(options ...func(o *Options)) error { //nolint:funlen,cyclop,gocognit,g
163181 sort .Strings (files )
164182
165183 if * output != "" && r .outDir == "" {
166- fn := * output
167-
168- out , err := os .Create (fn ) //nolint:gosec
184+ w , closer , err := makeWriter (* output )
169185 if err != nil {
170- return fmt .Errorf ("failed to create output file %s: %w" , fn , err )
171- }
172-
173- r .output = out
174- compCloser := io .Closer (io .NopCloser (nil ))
175-
176- switch {
177- case strings .HasSuffix (fn , ".gz" ):
178- gw := gzip .NewWriter (r .output )
179- compCloser = gw
180-
181- r .output = gw
182- case strings .HasSuffix (fn , ".zst" ):
183- zw , err := zstdWriter (r .output )
184- if err != nil {
185- return fmt .Errorf ("zstd new writer: %w" , err )
186- }
187-
188- compCloser = zw
189-
190- r .output = zw
186+ return err
191187 }
192188
193- w := bufio .NewWriterSize (r .output , 64 * 1024 )
194189 r .output = w
195190
196- defer func () {
197- if err := w .Flush (); err != nil {
198- log .Fatalf ("failed to flush STDOUT buffer: %s" , err )
199- }
200-
201- if err := compCloser .Close (); err != nil {
202- log .Fatalf ("failed to close compressor: %s" , err )
203- }
204-
205- if err := out .Close (); err != nil {
206- log .Fatalf ("failed to close output file %s: %s" , * output , err )
207- }
208- }()
191+ closers = append (closers , closer )
209192 } else {
210193 if isStdin {
211194 r .output = os .Stdout
212195 } else {
213196 w := bufio .NewWriterSize (os .Stdout , 64 * 1024 )
214197 r .output = w
215-
216- defer func () {
217- if err := w .Flush (); err != nil {
218- log .Fatalf ("failed to flush STDOUT buffer: %s" , err )
219- }
220- }()
198+ closers = append (closers , w .Flush )
221199 }
222200 }
223201
0 commit comments