1 extern crate regex;
2 
3 use regex::{Captures, Regex};
4 use std::collections::HashSet;
5 use std::io;
6 use std::io::{Read, Write};
7 
main()8 fn main() {
9     let mut buffer = String::new();
10     if let Err(e) = io::stdin().read_to_string(&mut buffer) {
11         panic!("{}", e);
12     }
13 
14     let mut refs = HashSet::new();
15 
16     // Capture all links and link references.
17     let regex =
18         r"\[([^\]]+)\](?:(?:\[([^\]]+)\])|(?:\([^\)]+\)))(?i)<!--\signore\s-->";
19     let link_regex = Regex::new(regex).unwrap();
20     let first_pass = link_regex.replace_all(&buffer, |caps: &Captures<'_>| {
21         // Save the link reference we want to delete.
22         if let Some(reference) = caps.get(2) {
23             refs.insert(reference.as_str().to_string());
24         }
25 
26         // Put the link title back.
27         caps.get(1).unwrap().as_str().to_string()
28     });
29 
30     // Search for the references we need to delete.
31     let ref_regex = Regex::new(r"(?m)^\[([^\]]+)\]:\s.*\n").unwrap();
32     let out = ref_regex.replace_all(&first_pass, |caps: &Captures<'_>| {
33         let capture = caps.get(1).unwrap().to_owned();
34 
35         // Check if we've marked this reference for deletion ...
36         if refs.contains(capture.as_str()) {
37             return "".to_string();
38         }
39 
40         // ... else we put back everything we captured.
41         caps.get(0).unwrap().as_str().to_string()
42     });
43 
44     write!(io::stdout(), "{}", out).unwrap();
45 }
46