]> git.proxmox.com Git - rustc.git/blame - src/doc/book/tools/src/bin/concat_chapters.rs
New upstream version 1.31.0~beta.19+dfsg1
[rustc.git] / src / doc / book / tools / src / bin / concat_chapters.rs
CommitLineData
13cf67c4
XL
1// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11#[macro_use] extern crate lazy_static;
12extern crate regex;
13
14use std::env;
15use std::io;
16use std::io::{Read, Write};
17use std::process::exit;
18use std::fs::{create_dir, read_dir, File};
19use std::path::{Path, PathBuf};
20use std::collections::BTreeMap;
21
22use regex::Regex;
23
24static PATTERNS: &'static [(&'static str, &'static str)] = &[
25 (r"ch(\d\d)-\d\d-.*\.md", "chapter$1.md"),
26 (r"appendix-(\d\d).*\.md", "appendix.md"),
27];
28
29lazy_static! {
30 static ref MATCHERS: Vec<(Regex, &'static str)> = {
31 PATTERNS.iter()
32 .map(|&(expr, repl)| (Regex::new(expr).unwrap(), repl))
33 .collect()
34 };
35}
36
37fn main() {
38 let args: Vec<String> = env::args().collect();
39
40 if args.len() < 3 {
41 println!("Usage: {} <src-dir> <target-dir>", args[0]);
42 exit(1);
43 }
44
45 let source_dir = ensure_dir_exists(&args[1]).unwrap();
46 let target_dir = ensure_dir_exists(&args[2]).unwrap();
47
48 let mut matched_files = match_files(source_dir, target_dir);
49 matched_files.sort();
50
51 for (target_path, source_paths) in group_by_target(matched_files) {
52 concat_files(source_paths, target_path).unwrap();
53 }
54}
55
56fn match_files(source_dir: &Path, target_dir: &Path) -> Vec<(PathBuf, PathBuf)> {
57 read_dir(source_dir)
58 .expect("Unable to read source directory")
59 .filter_map(|maybe_entry| maybe_entry.ok())
60 .filter_map(|entry| {
61 let source_filename = entry.file_name();
62 let source_filename = &source_filename.to_string_lossy().into_owned();
63 for &(ref regex, replacement) in MATCHERS.iter() {
64 if regex.is_match(source_filename) {
65 let target_filename = regex.replace_all(source_filename, replacement);
66 let source_path = entry.path();
67 let mut target_path = PathBuf::from(&target_dir);
68 target_path.push(target_filename);
69 return Some((source_path, target_path));
70 }
71 }
72 None
73 })
74 .collect()
75}
76
77fn group_by_target(matched_files: Vec<(PathBuf, PathBuf)>) -> BTreeMap<PathBuf, Vec<PathBuf>> {
78 let mut grouped: BTreeMap<PathBuf, Vec<PathBuf>> = BTreeMap::new();
79 for (source, target) in matched_files {
80 if let Some(source_paths) = grouped.get_mut(&target) {
81 source_paths.push(source);
82 continue;
83 }
84 let source_paths = vec![source];
85 grouped.insert(target.clone(), source_paths);
86 }
87 grouped
88}
89
90fn concat_files(source_paths: Vec<PathBuf>, target_path: PathBuf) -> io::Result<()> {
91 println!("Concatenating into {}:", target_path.to_string_lossy());
92 let mut target = try!(File::create(target_path));
93 try!(target.write_all(b"\n[TOC]\n"));
94
95 for path in source_paths {
96 println!(" {}", path.to_string_lossy());
97 let mut source = try!(File::open(path));
98 let mut contents: Vec<u8> = Vec::new();
99 try!(source.read_to_end(&mut contents));
100
101 try!(target.write_all(b"\n"));
102 try!(target.write_all(&contents));
103 try!(target.write_all(b"\n"));
104 }
105 Ok(())
106}
107
108fn ensure_dir_exists(dir_string: &str) -> io::Result<&Path> {
109 let path = Path::new(dir_string);
110 if !path.exists() {
111 try!(create_dir(path));
112 }
113 Ok(&path)
114}