]> git.proxmox.com Git - rustc.git/blame - src/doc/book/2018-edition/tools/src/bin/concat_chapters.rs
New upstream version 1.34.2+dfsg1
[rustc.git] / src / doc / book / 2018-edition / tools / src / bin / concat_chapters.rs
CommitLineData
83c7162d
XL
1#[macro_use] extern crate lazy_static;
2extern crate regex;
3
4use std::env;
5use std::io;
6use std::io::{Read, Write};
7use std::process::exit;
8use std::fs::{create_dir, read_dir, File};
9use std::path::{Path, PathBuf};
10use std::collections::BTreeMap;
11
12use regex::Regex;
13
14static PATTERNS: &'static [(&'static str, &'static str)] = &[
15 (r"ch(\d\d)-\d\d-.*\.md", "chapter$1.md"),
16 (r"appendix-(\d\d).*\.md", "appendix.md"),
17];
18
19lazy_static! {
20 static ref MATCHERS: Vec<(Regex, &'static str)> = {
21 PATTERNS.iter()
22 .map(|&(expr, repl)| (Regex::new(expr).unwrap(), repl))
23 .collect()
24 };
25}
26
27fn main() {
28 let args: Vec<String> = env::args().collect();
29
30 if args.len() < 3 {
31 println!("Usage: {} <src-dir> <target-dir>", args[0]);
32 exit(1);
33 }
34
35 let source_dir = ensure_dir_exists(&args[1]).unwrap();
36 let target_dir = ensure_dir_exists(&args[2]).unwrap();
37
38 let mut matched_files = match_files(source_dir, target_dir);
39 matched_files.sort();
40
41 for (target_path, source_paths) in group_by_target(matched_files) {
42 concat_files(source_paths, target_path).unwrap();
43 }
44}
45
46fn match_files(source_dir: &Path, target_dir: &Path) -> Vec<(PathBuf, PathBuf)> {
47 read_dir(source_dir)
48 .expect("Unable to read source directory")
49 .filter_map(|maybe_entry| maybe_entry.ok())
50 .filter_map(|entry| {
51 let source_filename = entry.file_name();
52 let source_filename = &source_filename.to_string_lossy().into_owned();
53 for &(ref regex, replacement) in MATCHERS.iter() {
54 if regex.is_match(source_filename) {
55 let target_filename = regex.replace_all(source_filename, replacement);
56 let source_path = entry.path();
57 let mut target_path = PathBuf::from(&target_dir);
58 target_path.push(target_filename);
59 return Some((source_path, target_path));
60 }
61 }
62 None
63 })
64 .collect()
65}
66
67fn group_by_target(matched_files: Vec<(PathBuf, PathBuf)>) -> BTreeMap<PathBuf, Vec<PathBuf>> {
68 let mut grouped: BTreeMap<PathBuf, Vec<PathBuf>> = BTreeMap::new();
69 for (source, target) in matched_files {
70 if let Some(source_paths) = grouped.get_mut(&target) {
71 source_paths.push(source);
72 continue;
73 }
74 let source_paths = vec![source];
75 grouped.insert(target.clone(), source_paths);
76 }
77 grouped
78}
79
80fn concat_files(source_paths: Vec<PathBuf>, target_path: PathBuf) -> io::Result<()> {
81 println!("Concatenating into {}:", target_path.to_string_lossy());
82 let mut target = try!(File::create(target_path));
83 try!(target.write_all(b"\n[TOC]\n"));
84
85 for path in source_paths {
86 println!(" {}", path.to_string_lossy());
87 let mut source = try!(File::open(path));
88 let mut contents: Vec<u8> = Vec::new();
89 try!(source.read_to_end(&mut contents));
90
91 try!(target.write_all(b"\n"));
92 try!(target.write_all(&contents));
93 try!(target.write_all(b"\n"));
94 }
95 Ok(())
96}
97
98fn ensure_dir_exists(dir_string: &str) -> io::Result<&Path> {
99 let path = Path::new(dir_string);
100 if !path.exists() {
101 try!(create_dir(path));
102 }
103 Ok(&path)
104}