e4f7561bcd
The entire testsuite is converted to using info! rather than debug! because some depend on the code within the debug! being trans'd.
287 lines
7.7 KiB
Rust
287 lines
7.7 KiB
Rust
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
|
// file at the top-level directory of this distribution and at
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
// option. This file may not be copied, modified, or distributed
|
|
// except according to those terms.
|
|
|
|
|
|
use config;
|
|
use doc::ItemUtils;
|
|
use doc;
|
|
|
|
use std::comm::*;
|
|
use std::comm;
|
|
use std::io;
|
|
use std::result;
|
|
use std::run;
|
|
use std::str;
|
|
use std::task;
|
|
use extra::future;
|
|
|
|
pub enum WriteInstr {
|
|
Write(~str),
|
|
Done
|
|
}
|
|
|
|
pub type Writer = ~fn(v: WriteInstr);
|
|
pub type WriterFactory = ~fn(page: doc::Page) -> Writer;
|
|
|
|
pub trait WriterUtils {
|
|
fn put_str(&self, str: ~str);
|
|
fn put_line(&self, str: ~str);
|
|
fn put_done(&self);
|
|
}
|
|
|
|
impl WriterUtils for Writer {
|
|
fn put_str(&self, str: ~str) {
|
|
(*self)(Write(str));
|
|
}
|
|
|
|
fn put_line(&self, str: ~str) {
|
|
self.put_str(str + "\n");
|
|
}
|
|
|
|
fn put_done(&self) {
|
|
(*self)(Done)
|
|
}
|
|
}
|
|
|
|
pub fn make_writer_factory(config: config::Config) -> WriterFactory {
|
|
match config.output_format {
|
|
config::Markdown => {
|
|
markdown_writer_factory(config)
|
|
}
|
|
config::PandocHtml => {
|
|
pandoc_writer_factory(config)
|
|
}
|
|
}
|
|
}
|
|
|
|
fn markdown_writer_factory(config: config::Config) -> WriterFactory {
|
|
let result: ~fn(page: doc::Page) -> Writer = |page| {
|
|
markdown_writer(&config, page)
|
|
};
|
|
result
|
|
}
|
|
|
|
fn pandoc_writer_factory(config: config::Config) -> WriterFactory {
|
|
let result: ~fn(doc::Page) -> Writer = |page| {
|
|
pandoc_writer(&config, page)
|
|
};
|
|
result
|
|
}
|
|
|
|
fn markdown_writer(
|
|
config: &config::Config,
|
|
page: doc::Page
|
|
) -> Writer {
|
|
let filename = make_local_filename(config, page);
|
|
do generic_writer |markdown| {
|
|
write_file(&filename, markdown);
|
|
}
|
|
}
|
|
|
|
fn pandoc_writer(
|
|
config: &config::Config,
|
|
page: doc::Page
|
|
) -> Writer {
|
|
assert!(config.pandoc_cmd.is_some());
|
|
let pandoc_cmd = copy *config.pandoc_cmd.get_ref();
|
|
let filename = make_local_filename(config, page);
|
|
|
|
let pandoc_args = ~[
|
|
~"--standalone",
|
|
~"--section-divs",
|
|
~"--from=markdown",
|
|
~"--to=html",
|
|
~"--css=rust.css",
|
|
~"--output=" + filename.to_str()
|
|
];
|
|
|
|
do generic_writer |markdown| {
|
|
use std::io::WriterUtil;
|
|
|
|
debug!("pandoc cmd: %s", pandoc_cmd);
|
|
debug!("pandoc args: %s", pandoc_args.connect(" "));
|
|
|
|
let mut proc = run::Process::new(pandoc_cmd, pandoc_args, run::ProcessOptions::new());
|
|
|
|
proc.input().write_str(markdown);
|
|
let output = proc.finish_with_output();
|
|
|
|
debug!("pandoc result: %i", output.status);
|
|
if output.status != 0 {
|
|
error!("pandoc-out: %s", str::from_bytes(output.output));
|
|
error!("pandoc-err: %s", str::from_bytes(output.error));
|
|
fail!("pandoc failed");
|
|
}
|
|
}
|
|
}
|
|
|
|
fn generic_writer(process: ~fn(markdown: ~str)) -> Writer {
|
|
let (po, ch) = stream::<WriteInstr>();
|
|
do task::spawn || {
|
|
let mut markdown = ~"";
|
|
let mut keep_going = true;
|
|
while keep_going {
|
|
match po.recv() {
|
|
Write(s) => markdown.push_str(s),
|
|
Done => keep_going = false
|
|
}
|
|
}
|
|
process(markdown);
|
|
};
|
|
let result: ~fn(instr: WriteInstr) = |instr| ch.send(instr);
|
|
result
|
|
}
|
|
|
|
pub fn make_local_filename(
|
|
config: &config::Config,
|
|
page: doc::Page
|
|
) -> Path {
|
|
let filename = make_filename(config, page);
|
|
config.output_dir.push_rel(&filename)
|
|
}
|
|
|
|
pub fn make_filename(
|
|
config: &config::Config,
|
|
page: doc::Page
|
|
) -> Path {
|
|
let filename = {
|
|
match page {
|
|
doc::CratePage(doc) => {
|
|
if config.output_format == config::PandocHtml &&
|
|
config.output_style == config::DocPerMod {
|
|
~"index"
|
|
} else {
|
|
assert!(doc.topmod.name() != ~"");
|
|
doc.topmod.name()
|
|
}
|
|
}
|
|
doc::ItemPage(doc) => {
|
|
(doc.path() + &[doc.name()]).connect("_")
|
|
}
|
|
}
|
|
};
|
|
let ext = match config.output_format {
|
|
config::Markdown => ~"md",
|
|
config::PandocHtml => ~"html"
|
|
};
|
|
|
|
Path(filename).with_filetype(ext)
|
|
}
|
|
|
|
fn write_file(path: &Path, s: ~str) {
|
|
use std::io::WriterUtil;
|
|
|
|
match io::file_writer(path, [io::Create, io::Truncate]) {
|
|
result::Ok(writer) => {
|
|
writer.write_str(s);
|
|
}
|
|
result::Err(e) => fail!(e)
|
|
}
|
|
}
|
|
|
|
pub fn future_writer_factory(
|
|
) -> (WriterFactory, Port<(doc::Page, ~str)>) {
|
|
let (markdown_po, markdown_ch) = stream();
|
|
let markdown_ch = SharedChan::new(markdown_ch);
|
|
let writer_factory: WriterFactory = |page| {
|
|
let (writer_po, writer_ch) = comm::stream();
|
|
let markdown_ch = markdown_ch.clone();
|
|
do task::spawn || {
|
|
let (writer, future) = future_writer();
|
|
let mut future = future;
|
|
writer_ch.send(writer);
|
|
let s = future.get();
|
|
markdown_ch.send((copy page, s));
|
|
}
|
|
writer_po.recv()
|
|
};
|
|
|
|
(writer_factory, markdown_po)
|
|
}
|
|
|
|
fn future_writer() -> (Writer, future::Future<~str>) {
|
|
let (port, chan) = comm::stream();
|
|
let writer: ~fn(instr: WriteInstr) = |instr| chan.send(copy instr);
|
|
let future = do future::from_fn || {
|
|
let mut res = ~"";
|
|
loop {
|
|
match port.recv() {
|
|
Write(s) => res.push_str(s),
|
|
Done => break
|
|
}
|
|
}
|
|
res
|
|
};
|
|
(writer, future)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
|
|
use astsrv;
|
|
use doc;
|
|
use extract;
|
|
use path_pass;
|
|
use config;
|
|
use super::make_local_filename;
|
|
|
|
fn mk_doc(name: ~str, source: ~str) -> doc::Doc {
|
|
do astsrv::from_str(source) |srv| {
|
|
let doc = extract::from_srv(srv.clone(), copy name);
|
|
let doc = (path_pass::mk_pass().f)(srv.clone(), doc);
|
|
doc
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn should_use_markdown_file_name_based_off_crate() {
|
|
let config = config::Config {
|
|
output_dir: Path("output/dir"),
|
|
output_format: config::Markdown,
|
|
output_style: config::DocPerCrate,
|
|
.. config::default_config(&Path("input/test.rc"))
|
|
};
|
|
let doc = mk_doc(~"test", ~"");
|
|
let page = doc::CratePage(doc.CrateDoc());
|
|
let filename = make_local_filename(&config, page);
|
|
assert_eq!(filename.to_str(), ~"output/dir/test.md");
|
|
}
|
|
|
|
#[test]
|
|
fn should_name_html_crate_file_name_index_html_when_doc_per_mod() {
|
|
let config = config::Config {
|
|
output_dir: Path("output/dir"),
|
|
output_format: config::PandocHtml,
|
|
output_style: config::DocPerMod,
|
|
.. config::default_config(&Path("input/test.rc"))
|
|
};
|
|
let doc = mk_doc(~"", ~"");
|
|
let page = doc::CratePage(doc.CrateDoc());
|
|
let filename = make_local_filename(&config, page);
|
|
assert_eq!(filename.to_str(), ~"output/dir/index.html");
|
|
}
|
|
|
|
#[test]
|
|
fn should_name_mod_file_names_by_path() {
|
|
let config = config::Config {
|
|
output_dir: Path("output/dir"),
|
|
output_format: config::PandocHtml,
|
|
output_style: config::DocPerMod,
|
|
.. config::default_config(&Path("input/test.rc"))
|
|
};
|
|
let doc = mk_doc(~"", ~"mod a { mod b { } }");
|
|
// hidden __std_macros module at the start.
|
|
let modb = copy doc.cratemod().mods()[1].mods()[0];
|
|
let page = doc::ItemPage(doc::ModTag(modb));
|
|
let filename = make_local_filename(&config, page);
|
|
assert_eq!(filename, Path("output/dir/a_b.html"));
|
|
}
|
|
}
|