1 // This package contains a CLI program to extract basic metadata from FASTQ formatted files. 2 package main // import "vimagination.zapto.org/idoneal" 3 4 import ( 5 "compress/gzip" 6 "flag" 7 "fmt" 8 "io" 9 "io/fs" 10 "os" 11 "strings" 12 13 "vimagination.zapto.org/idoneal/pkg/meta" 14 ) 15 16 type OS struct{} 17 18 func (OS) Open(name string) (fs.File, error) { 19 return os.Open(name) 20 } 21 22 // Vars to be mocked for testing 23 var ( 24 Stdout io.Writer = os.Stdout 25 Stderr io.Writer = os.Stderr 26 FS fs.FS = OS{} 27 Exit = os.Exit 28 flagErrorHandler = flag.ExitOnError 29 ) 30 31 func openFile(file string) (io.ReadCloser, error) { 32 var ( 33 f io.ReadCloser 34 err error 35 ) 36 f, err = FS.Open(file) 37 if err != nil { 38 return nil, fmt.Errorf("error opening file: %w\n", err) 39 } 40 if strings.HasSuffix(file, ".gz") { 41 f, err = gzip.NewReader(f) 42 if err != nil { 43 return nil, fmt.Errorf("error starting decompression: %w", err) 44 } 45 } 46 return f, nil 47 } 48 49 func main() { 50 var countSequences, countNucleotides bool 51 52 flags := flag.NewFlagSet(os.Args[0], flagErrorHandler) 53 flags.SetOutput(Stderr) 54 flags.Usage = func() { 55 fmt.Fprintf(Stderr, `Usage: %s [OPTIONS] FILE 56 57 OPTIONS: 58 -h, --help Print this help. 59 -n, --nucleotides Print the number of nucleotides in the FILE. 60 -s, --sequences Print the number of sequences in the FILE. 61 `, os.Args[0]) 62 } 63 flags.BoolVar(&countSequences, "s", false, "") 64 flags.BoolVar(&countSequences, "sequences", false, "") 65 flags.BoolVar(&countNucleotides, "n", false, "") 66 flags.BoolVar(&countNucleotides, "nucleotides", false, "") 67 flags.Parse(os.Args[1:]) 68 69 file := flags.Arg(0) 70 71 if file == "" { 72 flags.Usage() 73 return 74 } 75 76 if countSequences { 77 f, err := openFile(file) 78 if err != nil { 79 fmt.Fprintln(Stderr, err) 80 } 81 defer f.Close() 82 count, err := meta.CountSequences(f) 83 if err != nil { 84 fmt.Fprintf(Stderr, "error while counting sequences: %s\n", err) 85 Exit(2) 86 return 87 } 88 fmt.Fprintln(Stdout, count) 89 } 90 if countNucleotides { 91 f, err := openFile(file) 92 if err != nil { 93 fmt.Fprintln(Stderr, err) 94 } 95 defer f.Close() 96 count, err := meta.CountNucleotides(f) 97 if err != nil { 98 fmt.Fprintf(Stderr, "error while counting nucleotides: %s\n", err) 99 Exit(2) 100 return 101 } 102 fmt.Fprintln(Stdout, count) 103 } 104 } 105