diff --git a/Cargo.toml b/Cargo.toml index bb29c035..b9396c8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fasten" -version = "0.4.3" +version = "0.4.4" authors = ["Lee Katz "] #license-file = "LICENSE" license = "MIT" diff --git a/src/bin/fasten_clean.rs b/src/bin/fasten_clean.rs index b8686510..6416b128 100644 --- a/src/bin/fasten_clean.rs +++ b/src/bin/fasten_clean.rs @@ -39,12 +39,12 @@ extern crate threadpool; use std::fs::File; use std::io::BufReader; use std::io::BufRead; -use std::env; use threadpool::ThreadPool; use std::sync::mpsc::channel; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; //use fasten::logmsg; #[test] @@ -128,7 +128,6 @@ D>C1'02C+=I@IEFHC7&-E5',I?E*33E/@3#68B%\"!B-/2%(G=*@D052IA!('7-*$+A6>.$89,-CG71= } fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); // invisible option but maybe we can expose it: @@ -140,12 +139,7 @@ fn main(){ opts.optopt("","min-avg-quality","Minimum average quality for each read","FLOAT"); opts.optopt("","min-trim-quality","Trim the edges of each read until a nucleotide of at least X quality is found","INT"); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); - - if matches.opt_present("h") { - println!("{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Trims and filters reads", opts); let mut min_length :usize = 0; if matches.opt_present("min-length") { diff --git a/src/bin/fasten_combine.rs b/src/bin/fasten_combine.rs index 69f97be2..46c6db57 100644 --- a/src/bin/fasten_combine.rs +++ b/src/bin/fasten_combine.rs @@ -36,10 +36,10 @@ use std::io::stdin; //use std::io::BufRead; use std::collections::HashMap; -use std::env; use std::f32; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; use fastq::{Parser, Record}; use fasten::logmsg; @@ -51,7 +51,6 @@ const TEN: f32 = 10.0; const READ_SEPARATOR :char = '~'; fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); // make a string of characters like !"#...GHI to represent all quals @@ -72,15 +71,9 @@ fn main(){ format!("Minimum quality character (default: {})", default_phred_min_char).as_str(), "CHAR"); - let matches = opts.parse(&args[1..]).expect("Parsing parameters"); + let description:String = format!("Collapse identical reads into single reads, recalculating quality values. If paired end, then each set of reads must be identical to be collapsed. Warning: due to multiple reads collapsing into one, read identifiers will be reconstituted. NOTE: range of quality scores is {}", qual_range_string); + let matches = fasten_base_options_matches(&description, opts); - if matches.opt_present("h") { - println!("Collapse identical reads into single reads, recalculating quality values. If paired end, then each set of reads must be identical to be collapsed. Warning: due to multiple reads collapsing into one, read identifiers will be reconstituted."); - println!("{}",opts.usage(&opts.short_usage(&args[0]))); - println!("NOTE: range of quality scores is {}", qual_range_string); - std::process::exit(0); - } - let max_qual_char:char = matches.opt_default("max-qual-char", &default_phred_max_char.to_string()) .unwrap_or(String::from(default_phred_max_char)) .parse() diff --git a/src/bin/fasten_convert.rs b/src/bin/fasten_convert.rs index 447d4037..5049589d 100644 --- a/src/bin/fasten_convert.rs +++ b/src/bin/fasten_convert.rs @@ -38,13 +38,12 @@ extern crate bam; use bam::RecordReader; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; use fasten::logmsg; use std::io::stdin; use fastq::{Parser, Record}; -use std::env; - use std::sync::mpsc::channel; /// Struct that can handle paired end reads @@ -123,16 +122,12 @@ fn test_fastq_to () { */ fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); - opts.optopt("i", "in-format", "The input format for stdin", "FORMAT"); - opts.optopt("o", "out-format", "The output format for stdin", "FORMAT"); + opts.optopt("i", "in-format", "The input format for stdin. FORMAT can be: fastq, fasta, sam.", "FORMAT"); + opts.optopt("o", "out-format", "The output format for stdin. See --in-format for FORMAT options.", "FORMAT"); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); - if matches.opt_present("help") { - println!("{} FORMAT can be: fastq, fasta, sam\n", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let description:String = format!("Converts between sequence formats."); + let matches = fasten_base_options_matches(&description, opts); let paired_end = matches.opt_present("paired-end"); diff --git a/src/bin/fasten_kmer.rs b/src/bin/fasten_kmer.rs index a4eef0d0..891fdb5c 100644 --- a/src/bin/fasten_kmer.rs +++ b/src/bin/fasten_kmer.rs @@ -27,11 +27,11 @@ extern crate getopts; use std::io::BufReader; use std::io::BufRead; -use std::env; use std::io::stdin; use std::io::Stdin; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; use fasten::logmsg; use std::collections::HashMap; @@ -85,7 +85,6 @@ fn test_kmer_counting_4mers () { } fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); // script-specific options @@ -93,12 +92,8 @@ fn main(){ opts.optopt("k","kmer-length",&format!("The size of the kmer (default: {})",default_k),"INT"); opts.optflag("r","revcomp", "Count kmers on the reverse complement strand too"); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); - - if matches.opt_present("help") { - println!("Counts kmers.\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Counts kmers.", opts); + if matches.opt_present("paired-end") { logmsg("WARNING: --paired-end is not utilized in this script"); } diff --git a/src/bin/fasten_metrics.rs b/src/bin/fasten_metrics.rs index f5c61091..2482ef43 100644 --- a/src/bin/fasten_metrics.rs +++ b/src/bin/fasten_metrics.rs @@ -33,9 +33,8 @@ use std::io::BufReader; use std::io::BufRead; use std::f32; -use std::env; - use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; use fasten::logmsg; #[test] @@ -53,19 +52,14 @@ fn test_average_quality () { } fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); // script-specific options opts.optflag("","each-read","Print the metrics for each read. This creates very large output"); opts.optopt("","distribution","Print the distribution for each metric. Must supply either 'normal' or 'nonparametric'","STRING"); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); + let matches = fasten_base_options_matches("Gives read metrics on a read set.", opts); - if matches.opt_present("help") { - println!("Gives read metrics on a read set.\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } if matches.opt_present("paired-end") { logmsg("WARNING: --paired-end is not utilized in this script"); } diff --git a/src/bin/fasten_mutate.rs b/src/bin/fasten_mutate.rs index a7856ae8..2fcf43d7 100644 --- a/src/bin/fasten_mutate.rs +++ b/src/bin/fasten_mutate.rs @@ -29,26 +29,21 @@ extern crate rand; use std::fs::File; use std::io::BufReader; use std::io::BufRead; -use std::env; use rand::distributions::{IndependentSample, Range}; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; use fasten::logmsg; fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); // Options specific to this script opts.optopt("s", "snps", "Number of SNPs (point mutations) to include per read.", "INT"); opts.optflag("m", "mark", "lowercase all reads but uppercase the SNPs (not yet implemented)"); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); - if matches.opt_present("help") { - println!("Mutates reads. There is no mutation model; only randomness.\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Mutates reads. There is no mutation model; only randomness.", opts); if matches.opt_present("paired-end") { logmsg("WARNING: --paired-end is not utilized in this script"); diff --git a/src/bin/fasten_pe.rs b/src/bin/fasten_pe.rs index c44a45bf..d997a991 100644 --- a/src/bin/fasten_pe.rs +++ b/src/bin/fasten_pe.rs @@ -28,27 +28,19 @@ extern crate fasten; extern crate regex; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; use fasten::logmsg; use regex::Regex; use std::fs::File; use std::io::BufReader; use std::io::BufRead; -use std::env; fn main() { - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); - //opts.optopt("c","check-first","How many deflines to check to make sure the input is paired-end","INT"); opts.optflag("","print-reads","Print each read. Useful for Unix pipes."); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); + let matches = fasten_base_options_matches("Determine paired-end-ness in an interleaved file. Exit code of 0 indicates PE. Exit code > 0 indicates SE.", opts); - if matches.opt_present("help") { - println!("Determine paired-end-ness in an interleaved file. Exit code of 0 indicates PE. Exit code > 0 indicates SE.\n{}", - opts.usage(&opts.short_usage(&args[0])) - ); - std::process::exit(0); - } if matches.opt_present("paired-end") { logmsg("WARNING: --paired-end was supplied but this script is supposed to determine whether the input is paired-end."); } diff --git a/src/bin/fasten_progress.rs b/src/bin/fasten_progress.rs index b2ea0725..2d83e9e4 100644 --- a/src/bin/fasten_progress.rs +++ b/src/bin/fasten_progress.rs @@ -48,23 +48,18 @@ extern crate fasten; use std::fs::File; use std::io::BufReader; use std::io::BufRead; -use std::env; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); // Options specific to this script opts.optopt("","id","Progress identifier. Default: unnamed","STRING"); opts.optopt("","update-every","Update progress every n reads.","INT"); opts.optflag("p","print","Print the reads back to stdout"); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); - if matches.opt_present("help") { - println!("Prints a progress meter for number of fastq entries.\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Prints a progress meter for number of fastq entries", opts); let print_reads:bool = matches.opt_present("print"); diff --git a/src/bin/fasten_quality_filter.rs b/src/bin/fasten_quality_filter.rs index 32877070..beb27728 100644 --- a/src/bin/fasten_quality_filter.rs +++ b/src/bin/fasten_quality_filter.rs @@ -27,24 +27,19 @@ extern crate getopts; use std::fs::File; use std::io::BufReader; use std::io::BufRead; -use std::env; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; use fasten::logmsg; fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); // script-specific options opts.optopt("m","max-quality","The maximum quality at which a base will be transformed to 'N'","INT"); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); - - if matches.opt_present("help") { - println!("Transforms any low-quality base to 'N'\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Transforms any low-quality base to 'N'.", opts); + if matches.opt_present("paired-end") { logmsg("WARNING: --paired-end is not utilized in this script"); } diff --git a/src/bin/fasten_randomize.rs b/src/bin/fasten_randomize.rs index 81e0c2bd..2c014870 100644 --- a/src/bin/fasten_randomize.rs +++ b/src/bin/fasten_randomize.rs @@ -39,22 +39,16 @@ extern crate rand; use std::fs::File; use std::io::BufReader; use std::io::BufRead; -use std::env; use rand::{Rng,thread_rng}; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; fn main(){ - let args: Vec = env::args().collect(); let opts = fasten_base_options(); - //script-specific flags - let matches = opts.parse(&args[1..]).expect("Error: could not parse parameters"); - if matches.opt_present("help") { - println!("Create random reads from stdin.\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Create random reads from stdin.", opts); let lines_per_read :u32={ if matches.opt_present("paired-end") { diff --git a/src/bin/fasten_regex.rs b/src/bin/fasten_regex.rs index 199ca5c8..3170323b 100644 --- a/src/bin/fasten_regex.rs +++ b/src/bin/fasten_regex.rs @@ -37,27 +37,22 @@ extern crate threadpool; use std::fs::File; use std::io::BufReader; use std::io::BufRead; -use std::env; use regex::Regex; use threadpool::ThreadPool; use std::sync::mpsc::channel; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); // Options specific to this script opts.optopt("r","regex","Regular expression (default: '.')","STRING"); opts.optopt("w","which","Which field to match on? ID, SEQ, QUAL. Default: SEQ","String"); //opts.optflag("e","exclude","Exclude these reads instead of including them"); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); - if matches.opt_present("help") { - println!("Filter reads based on a regular expression.\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Filter reads based on a regular expression.", opts); let (tx, rx):(std::sync::mpsc::Sender,std::sync::mpsc::Receiver) = channel(); diff --git a/src/bin/fasten_replace.rs b/src/bin/fasten_replace.rs index 00c6495c..04790129 100644 --- a/src/bin/fasten_replace.rs +++ b/src/bin/fasten_replace.rs @@ -32,26 +32,21 @@ extern crate regex; use std::fs::File; use std::io::BufReader; use std::io::BufRead; -use std::env; use regex::Regex; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; use fasten::logmsg; fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); // Options specific to this script opts.optopt("f","find","Regular expression (default: '.')","STRING"); opts.optopt("r","replace","String to replace each match","STRING"); opts.optopt("w","which","Which field to match on? ID, SEQ, QUAL. Default: SEQ","STRING"); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); - if matches.opt_present("help") { - println!("Streaming editor for fastq data using a find/replace.\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Streaming editor for fastq data using a find/replace.", opts); if matches.opt_present("paired-end") { logmsg("WARNING: --paired-end is not utilized in this script"); diff --git a/src/bin/fasten_sample.rs b/src/bin/fasten_sample.rs index 36097b28..f0eb592f 100644 --- a/src/bin/fasten_sample.rs +++ b/src/bin/fasten_sample.rs @@ -29,25 +29,18 @@ use std::fs::File; use std::io::BufReader; use std::io::BufRead; -use std::env; - use rand::thread_rng; use rand::Rng; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); opts.optopt("f","frequency","Frequency of sequences to print, 0 to 1. Default: 1","FLOAT"); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); - - if matches.opt_present("help") { - println!("Ursula: downsample your reads\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Downsample your reads", opts); let frequency :f32 = { if matches.opt_present("frequency") { diff --git a/src/bin/fasten_shuffle.rs b/src/bin/fasten_shuffle.rs index 13952f33..a54e8350 100644 --- a/src/bin/fasten_shuffle.rs +++ b/src/bin/fasten_shuffle.rs @@ -52,26 +52,21 @@ use std::io::Write; use std::io::BufReader; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; use fasten::io::fastq; use fasten::io::seq::Cleanable; use fasten::io::seq::Seq; use fasten::logmsg; -use std::env; - fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); //script-specific flags opts.optflag("d","deshuffle","Deshuffle reads from stdin"); opts.optopt("1","","Forward reads. If deshuffling, reads are written to this file.","1.fastq"); opts.optopt("2","","Forward reads. If deshuffling, reads are written to this file.","2.fastq"); - let matches = opts.parse(&args[1..]).expect("Error: could not parse parameters"); - if matches.opt_present("help") { - println!("Interleaves reads from either stdin or file parameters.\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Interleaves reads from either stdin or file parameters", opts); + if matches.opt_present("paired-end") { logmsg("WARNING: --paired-end was supplied but it is assumed for this script anyway"); } diff --git a/src/bin/fasten_sort.rs b/src/bin/fasten_sort.rs index 2bbd350c..a4e7d4a2 100644 --- a/src/bin/fasten_sort.rs +++ b/src/bin/fasten_sort.rs @@ -55,9 +55,9 @@ extern crate threadpool; use std::fs::File; use std::io::BufReader; use std::io::BufRead; -use std::env; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; //use fasten::logmsg; #[test] @@ -137,17 +137,12 @@ struct Seq { } fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); // Options specific to this script opts.optopt("s","sort-by","Sort by either SEQ, GC, or ID. If GC, then the entries are sorted by GC percentage. SEQ and ID are alphabetically sorted.","STRING"); opts.optflag("r","reverse","Reverse sort"); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); - if matches.opt_present("help") { - println!("Sort reads.\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Sort reads. This can be useful for many things including checksums and reducing gzip file sizes. Remember to use --paired-end if applicable.", opts); let my_file = File::open("/dev/stdin").expect("Could not open file"); let my_buffer=BufReader::new(my_file); @@ -235,6 +230,7 @@ fn sort_entries (unsorted:Vec, which_field:&str, reverse_sort:bool) -> Vec< let mut sorted = unsorted.clone(); // Actual sort + // TODO sort by length? match which_field{ "ID" => { sorted.sort_by(|a, b| { diff --git a/src/bin/fasten_straighten.rs b/src/bin/fasten_straighten.rs index 328f5748..842613d0 100644 --- a/src/bin/fasten_straighten.rs +++ b/src/bin/fasten_straighten.rs @@ -24,12 +24,11 @@ use std::fs::File; use std::io::BufReader; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; use fasten::io::fastq; use fasten::io::seq::Cleanable; use fasten::logmsg; -use std::env; - #[test] /// Test to see whether we read the challenge dataset correctly fn challenge_dataset () { @@ -56,13 +55,9 @@ fn challenge_dataset () { fn main(){ - let args: Vec = env::args().collect(); let opts = fasten_base_options(); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); - if matches.opt_present("help") { - println!("Convert a fastq file to a standard 4-lines-per-entry format\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Convert a fastq file to a standard 4-lines-per-entry format", opts); + if matches.opt_present("paired-end") { logmsg("WARNING: --paired-end is not utilized in this script"); } diff --git a/src/bin/fasten_trim.rs b/src/bin/fasten_trim.rs index 6f5ff03c..4d7dfc10 100644 --- a/src/bin/fasten_trim.rs +++ b/src/bin/fasten_trim.rs @@ -39,32 +39,26 @@ extern crate threadpool; use std::fs::File; use std::io::BufReader; -use std::env; use std::cmp::min; use threadpool::ThreadPool; use std::sync::mpsc::channel; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; use fasten::logmsg; use fasten::io::fastq; use fasten::io::seq::Cleanable; use fasten::io::seq::Seq; fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); // script-specific options opts.optopt("f","first-base","The first base to keep (default: 0)","INT"); opts.optopt("l","last-base","The last base to keep. If negative, counts from the right. (default: 0)","INT"); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); - - if matches.opt_present("help") { - println!("Blunt-end trims using 0-based coordinates\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Blunt-end trims using 0-based coordinates", opts); let (tx, rx):(std::sync::mpsc::Sender,std::sync::mpsc::Receiver) = channel(); diff --git a/src/bin/fasten_validate.rs b/src/bin/fasten_validate.rs index 94a61b81..ebc012e3 100644 --- a/src/bin/fasten_validate.rs +++ b/src/bin/fasten_validate.rs @@ -41,7 +41,6 @@ //! --paired-end The reads are interleaved paired-end //! --print-reads Print the reads as they are being validated (useful //! for unix pipes) -//! -v, --verbose //! ``` extern crate getopts; @@ -50,27 +49,21 @@ extern crate regex; use std::fs::File; use std::io::BufReader; use std::io::BufRead; -use std::env; use regex::Regex; use fasten::fasten_base_options; +use fasten::fasten_base_options_matches; fn main(){ - let args: Vec = env::args().collect(); let mut opts = fasten_base_options(); // Options specific to this script opts.optopt("","min-length","Minimum read length allowed","INT"); opts.optopt("","min-quality","Minimum quality allowed","FLOAT"); opts.optflag("","paired-end","The reads are interleaved paired-end"); opts.optflag("","print-reads","Print the reads as they are being validated (useful for unix pipes)"); - opts.optflag("v","verbose",""); - let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); - if matches.opt_present("help") { - println!("Validates your reads and makes you feel good about yourself!\n{}", opts.usage(&opts.short_usage(&args[0]))); - std::process::exit(0); - } + let matches = fasten_base_options_matches("Validates your reads and makes you feel good about yourself!", opts); let my_file = File::open("/dev/stdin").expect("Could not open file"); let my_buffer=BufReader::new(my_file); diff --git a/src/lib.rs b/src/lib.rs index a0956134..67d8d139 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,10 +67,13 @@ use std::env; use std::path::Path; use getopts::Options; +use getopts::Matches; /// input/output methods pub mod io; +const VERSION: &'static str = env!("CARGO_PKG_VERSION"); + /// Have some strings that can be printed which could be /// used to propagate errors between piped scripts. @@ -112,11 +115,44 @@ pub fn fasten_base_options() -> Options{ opts.optflag("h", "help", "Print this help menu."); opts.optopt("n","numcpus","Number of CPUs (default: 1)","INT"); opts.optflag("p","paired-end","The input reads are interleaved paired-end"); - opts.optflag("v","verbose","Print more status messages"); + opts.optflag("","verbose","Print more status messages"); + opts.optflag("","version","Print the version of Fasten and exit"); return opts; } +/// a function that processes the options on the command line +/// The brief is a str that describes the program without using the program +/// name, e.g., "counts kmers" for fasten_kmer. +/// This function also takes care of --version. +/// If --help is invoked, then the program name, the brief, and the usage() +/// are all printed to stdout and then the program exits with 0. +// TODO if possible add in default somehow for numcpus +pub fn fasten_base_options_matches(brief:&str, opts:Options) -> Matches{ + let args: Vec = env::args().collect(); + let matches = opts.parse(&args[1..]).expect("ERROR: could not parse parameters"); + + if matches.opt_present("version") { + println!("Fasten v{}", &VERSION); + std::process::exit(0); + } + if matches.opt_present("h") { + let prog_name = Path::new(&args[0]) + .file_stem().unwrap() + .to_str().unwrap(); + println!("{}: {}\n\n{}", + &prog_name, + &brief, + &opts.usage( + &opts.short_usage(&prog_name) + ), + ); + std::process::exit(0); + } + + return matches; +} + /// Print a formatted message to stderr pub fn logmsg>(stringlike: S) { let args: Vec<_> = env::args().collect();