1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use crate::utils::{error, stdin};
use anyhow::{bail, Result};
use bio::io::fasta;
use regex::Regex;
use std::io;
pub fn regex_sequences(matches: &clap::ArgMatches) -> Result<()> {
let input_file = crate::get_fasta_files(matches);
let re_str = matches
.get_one::<String>("regex")
.expect("required by clap");
let inverse: bool = matches.get_flag("inverse");
let re = Regex::new(re_str);
let re = match re {
Ok(r) => r,
Err(e) => {
let err = format!(
"{}\nError: [-]\tActual error: {}",
error::RegexError::CouldNotCompile,
e
);
bail!(err)
}
};
// writer here?
let mut writer = fasta::Writer::new(io::stdout());
match input_file {
// read directly from files
Some(f) => {
for el in f.iter() {
let basename = crate::get_basename_from_pathbuf(el)?;
let reader = fasta::Reader::from_file(el)?;
for record in reader.records() {
let record = record?;
let id = record.id();
let description = record.desc().unwrap_or("");
let id_desc = format!("{} {}", id, description);
// if there is no match, we want to have
// the option to print
if re.is_match(&id_desc) {
if !inverse {
writer
.write(
id,
Some(&format!("{} - {}", description, basename)),
record.seq(),
)
.map_err(|_| error::FastaWriteError::CouldNotWrite)?;
} else {
continue;
}
} else if inverse {
writer
.write(
id,
Some(&format!("{} - {}", description, basename)),
record.seq(),
)
.map_err(|_| error::FastaWriteError::CouldNotWrite)?;
}
}
}
}
// read from stdin
None => match stdin::is_stdin() {
true => {
let mut records = fasta::Reader::new(io::stdin()).records();
while let Some(Ok(record)) = records.next() {
let id = record.id();
let description = record.desc().unwrap_or("");
let id_desc = format!("{} {}", id, description);
if re.is_match(&id_desc) {
if !inverse {
writer
.write(id, Some(description), record.seq())
.map_err(|_| error::FastaWriteError::CouldNotWrite)?;
} else {
continue;
}
} else if inverse {
writer
.write(id, Some(description), record.seq())
.map_err(|_| error::FastaWriteError::CouldNotWrite)?;
}
}
}
false => {
bail!(error::StdinError::NoSequence)
}
},
}
Ok(())
}