2013-05-30 05:16:33 -05:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// 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.
|
|
|
|
|
2013-05-17 17:28:44 -05:00
|
|
|
|
2012-12-23 16:41:37 -06:00
|
|
|
use config;
|
2012-09-18 18:48:40 -05:00
|
|
|
use doc::ItemUtils;
|
2012-12-23 16:41:37 -06:00
|
|
|
use doc;
|
|
|
|
|
2013-06-28 17:32:26 -05:00
|
|
|
use std::comm::*;
|
|
|
|
use std::comm;
|
|
|
|
use std::io;
|
|
|
|
use std::result;
|
|
|
|
use std::run;
|
|
|
|
use std::str;
|
|
|
|
use std::task;
|
2013-05-19 13:17:49 -05:00
|
|
|
use extra::future;
|
2012-07-11 17:00:40 -05:00
|
|
|
|
2013-07-02 14:47:32 -05:00
|
|
|
#[deriving(Clone)]
|
2012-11-19 20:00:12 -06:00
|
|
|
pub enum WriteInstr {
|
2012-09-18 18:48:40 -05:00
|
|
|
Write(~str),
|
|
|
|
Done
|
2012-03-01 00:26:28 -06:00
|
|
|
}
|
|
|
|
|
2013-03-01 18:02:22 -06:00
|
|
|
pub type Writer = ~fn(v: WriteInstr);
|
|
|
|
pub type WriterFactory = ~fn(page: doc::Page) -> Writer;
|
2012-03-01 00:26:28 -06:00
|
|
|
|
2012-11-19 20:00:12 -06:00
|
|
|
pub trait WriterUtils {
|
2013-05-07 16:20:56 -05:00
|
|
|
fn put_str(&self, str: ~str);
|
|
|
|
fn put_line(&self, str: ~str);
|
2013-03-20 14:49:22 -05:00
|
|
|
fn put_done(&self);
|
2012-07-11 17:00:40 -05:00
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl WriterUtils for Writer {
|
2013-03-20 14:49:22 -05:00
|
|
|
fn put_str(&self, str: ~str) {
|
2013-01-30 21:56:17 -06:00
|
|
|
(*self)(Write(str));
|
2012-03-01 00:26:28 -06:00
|
|
|
}
|
|
|
|
|
2013-03-20 14:49:22 -05:00
|
|
|
fn put_line(&self, str: ~str) {
|
2013-05-27 18:04:00 -05:00
|
|
|
self.put_str(str + "\n");
|
2012-03-01 00:26:28 -06:00
|
|
|
}
|
|
|
|
|
2013-03-20 14:49:22 -05:00
|
|
|
fn put_done(&self) {
|
2013-01-30 21:56:17 -06:00
|
|
|
(*self)(Done)
|
2012-03-01 00:26:28 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
pub fn make_writer_factory(config: config::Config) -> WriterFactory {
|
2012-08-06 14:34:08 -05:00
|
|
|
match config.output_format {
|
2012-09-18 18:48:40 -05:00
|
|
|
config::Markdown => {
|
2012-03-04 01:56:38 -06:00
|
|
|
markdown_writer_factory(config)
|
2012-03-01 16:21:14 -06:00
|
|
|
}
|
2012-09-18 18:48:40 -05:00
|
|
|
config::PandocHtml => {
|
2012-03-04 01:56:38 -06:00
|
|
|
pandoc_writer_factory(config)
|
2012-03-01 16:21:14 -06:00
|
|
|
}
|
|
|
|
}
|
2012-03-01 00:26:28 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn markdown_writer_factory(config: config::Config) -> WriterFactory {
|
2013-03-01 18:02:22 -06:00
|
|
|
let result: ~fn(page: doc::Page) -> Writer = |page| {
|
2013-05-22 05:54:35 -05:00
|
|
|
markdown_writer(&config, page)
|
2013-03-01 18:02:22 -06:00
|
|
|
};
|
|
|
|
result
|
2012-03-04 01:56:38 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn pandoc_writer_factory(config: config::Config) -> WriterFactory {
|
2013-03-01 18:02:22 -06:00
|
|
|
let result: ~fn(doc::Page) -> Writer = |page| {
|
2013-05-22 05:54:35 -05:00
|
|
|
pandoc_writer(&config, page)
|
2013-03-01 18:02:22 -06:00
|
|
|
};
|
|
|
|
result
|
2012-03-04 01:56:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn markdown_writer(
|
2013-05-22 05:54:35 -05:00
|
|
|
config: &config::Config,
|
2013-01-30 21:32:36 -06:00
|
|
|
page: doc::Page
|
2012-09-18 18:48:40 -05:00
|
|
|
) -> Writer {
|
2012-03-06 17:57:36 -06:00
|
|
|
let filename = make_local_filename(config, page);
|
2012-06-30 18:19:07 -05:00
|
|
|
do generic_writer |markdown| {
|
2012-08-24 17:28:43 -05:00
|
|
|
write_file(&filename, markdown);
|
2012-03-01 16:21:14 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-04 01:56:38 -06:00
|
|
|
fn pandoc_writer(
|
2013-05-22 05:54:35 -05:00
|
|
|
config: &config::Config,
|
2013-01-30 21:32:36 -06:00
|
|
|
page: doc::Page
|
2012-09-18 18:48:40 -05:00
|
|
|
) -> Writer {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(config.pandoc_cmd.is_some());
|
2013-07-02 14:47:32 -05:00
|
|
|
let pandoc_cmd = (*config.pandoc_cmd.get_ref()).clone();
|
2012-03-06 17:57:36 -06:00
|
|
|
let filename = make_local_filename(config, page);
|
2012-03-01 16:21:14 -06:00
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
let pandoc_args = ~[
|
2012-07-14 00:57:48 -05:00
|
|
|
~"--standalone",
|
|
|
|
~"--section-divs",
|
|
|
|
~"--from=markdown",
|
|
|
|
~"--to=html",
|
|
|
|
~"--css=rust.css",
|
2012-08-24 17:28:43 -05:00
|
|
|
~"--output=" + filename.to_str()
|
2012-06-29 18:26:56 -05:00
|
|
|
];
|
2012-03-01 16:21:14 -06:00
|
|
|
|
2012-06-30 18:19:07 -05:00
|
|
|
do generic_writer |markdown| {
|
2013-08-29 16:20:48 -05:00
|
|
|
use std::io::WriterUtil;
|
|
|
|
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("pandoc cmd: %s", pandoc_cmd);
|
2013-06-10 08:25:25 -05:00
|
|
|
debug!("pandoc args: %s", pandoc_args.connect(" "));
|
2012-03-01 16:21:14 -06:00
|
|
|
|
2013-08-29 16:20:48 -05:00
|
|
|
let mut proc = run::Process::new(pandoc_cmd, pandoc_args, run::ProcessOptions::new());
|
2012-03-01 16:21:14 -06:00
|
|
|
|
2013-08-29 16:20:48 -05:00
|
|
|
proc.input().write_str(markdown);
|
2013-05-12 07:58:00 -05:00
|
|
|
let output = proc.finish_with_output();
|
2012-03-01 16:21:14 -06:00
|
|
|
|
2013-05-12 07:58:00 -05:00
|
|
|
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));
|
2013-05-05 17:18:51 -05:00
|
|
|
fail!("pandoc failed");
|
2012-03-01 16:21:14 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-01 18:02:22 -06:00
|
|
|
fn generic_writer(process: ~fn(markdown: ~str)) -> Writer {
|
2013-02-01 20:03:32 -06:00
|
|
|
let (po, ch) = stream::<WriteInstr>();
|
2013-02-15 02:37:08 -06:00
|
|
|
do task::spawn || {
|
2012-07-14 00:57:48 -05:00
|
|
|
let mut markdown = ~"";
|
2012-03-22 10:39:41 -05:00
|
|
|
let mut keep_going = true;
|
2012-03-01 00:26:28 -06:00
|
|
|
while keep_going {
|
2012-11-28 22:34:40 -06:00
|
|
|
match po.recv() {
|
2013-06-11 21:13:42 -05:00
|
|
|
Write(s) => markdown.push_str(s),
|
2012-09-18 18:48:40 -05:00
|
|
|
Done => keep_going = false
|
2012-03-01 00:26:28 -06:00
|
|
|
}
|
|
|
|
}
|
2013-02-15 02:37:08 -06:00
|
|
|
process(markdown);
|
2012-03-01 00:26:28 -06:00
|
|
|
};
|
2013-03-01 18:02:22 -06:00
|
|
|
let result: ~fn(instr: WriteInstr) = |instr| ch.send(instr);
|
|
|
|
result
|
2012-03-01 00:26:28 -06:00
|
|
|
}
|
|
|
|
|
2013-04-15 10:09:55 -05:00
|
|
|
pub fn make_local_filename(
|
2013-05-22 05:54:35 -05:00
|
|
|
config: &config::Config,
|
2013-01-30 21:32:36 -06:00
|
|
|
page: doc::Page
|
2012-08-24 17:28:43 -05:00
|
|
|
) -> Path {
|
2013-05-22 05:54:35 -05:00
|
|
|
let filename = make_filename(config, page);
|
2012-08-24 17:28:43 -05:00
|
|
|
config.output_dir.push_rel(&filename)
|
2012-03-06 17:57:36 -06:00
|
|
|
}
|
2012-03-01 00:26:28 -06:00
|
|
|
|
2012-11-19 20:00:12 -06:00
|
|
|
pub fn make_filename(
|
2013-05-22 05:54:35 -05:00
|
|
|
config: &config::Config,
|
2013-01-30 21:32:36 -06:00
|
|
|
page: doc::Page
|
2012-08-24 17:28:43 -05:00
|
|
|
) -> Path {
|
2012-03-04 02:23:54 -06:00
|
|
|
let filename = {
|
2012-08-06 14:34:08 -05:00
|
|
|
match page {
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::CratePage(doc) => {
|
|
|
|
if config.output_format == config::PandocHtml &&
|
|
|
|
config.output_style == config::DocPerMod {
|
2012-07-14 00:57:48 -05:00
|
|
|
~"index"
|
2012-03-04 02:23:54 -06:00
|
|
|
} else {
|
2013-07-19 06:51:37 -05:00
|
|
|
assert!(doc.topmod.name_() != ~"");
|
|
|
|
doc.topmod.name_()
|
2012-03-04 02:23:54 -06:00
|
|
|
}
|
|
|
|
}
|
2012-09-18 18:48:40 -05:00
|
|
|
doc::ItemPage(doc) => {
|
2013-07-19 06:51:37 -05:00
|
|
|
(doc.path() + &[doc.name_()]).connect("_")
|
2012-03-04 02:23:54 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2012-08-06 14:34:08 -05:00
|
|
|
let ext = match config.output_format {
|
2012-09-18 18:48:40 -05:00
|
|
|
config::Markdown => ~"md",
|
|
|
|
config::PandocHtml => ~"html"
|
2012-03-04 02:23:54 -06:00
|
|
|
};
|
2012-03-06 17:57:36 -06:00
|
|
|
|
2012-08-24 17:28:43 -05:00
|
|
|
Path(filename).with_filetype(ext)
|
2012-03-01 00:26:28 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 21:32:36 -06:00
|
|
|
fn write_file(path: &Path, s: ~str) {
|
2013-06-28 17:32:26 -05:00
|
|
|
use std::io::WriterUtil;
|
2012-03-04 02:23:54 -06:00
|
|
|
|
2013-05-21 08:55:07 -05:00
|
|
|
match io::file_writer(path, [io::Create, io::Truncate]) {
|
2012-08-26 18:54:31 -05:00
|
|
|
result::Ok(writer) => {
|
2012-03-04 02:23:54 -06:00
|
|
|
writer.write_str(s);
|
|
|
|
}
|
2013-02-11 21:26:38 -06:00
|
|
|
result::Err(e) => fail!(e)
|
2012-03-04 02:23:54 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-19 20:00:12 -06:00
|
|
|
pub fn future_writer_factory(
|
2013-02-01 20:19:57 -06:00
|
|
|
) -> (WriterFactory, Port<(doc::Page, ~str)>) {
|
|
|
|
let (markdown_po, markdown_ch) = stream();
|
2013-04-17 01:45:29 -05:00
|
|
|
let markdown_ch = SharedChan::new(markdown_ch);
|
2013-03-01 18:02:22 -06:00
|
|
|
let writer_factory: WriterFactory = |page| {
|
2013-02-02 05:10:12 -06:00
|
|
|
let (writer_po, writer_ch) = comm::stream();
|
2013-02-01 20:19:57 -06:00
|
|
|
let markdown_ch = markdown_ch.clone();
|
2013-02-15 02:37:08 -06:00
|
|
|
do task::spawn || {
|
2012-03-04 01:56:38 -06:00
|
|
|
let (writer, future) = future_writer();
|
2013-05-03 13:30:30 -05:00
|
|
|
let mut future = future;
|
2013-02-15 02:37:08 -06:00
|
|
|
writer_ch.send(writer);
|
2012-12-11 17:19:43 -06:00
|
|
|
let s = future.get();
|
2013-07-02 14:47:32 -05:00
|
|
|
markdown_ch.send((page.clone(), s));
|
2012-03-04 01:56:38 -06:00
|
|
|
}
|
2012-11-28 22:34:40 -06:00
|
|
|
writer_po.recv()
|
2012-03-04 01:56:38 -06:00
|
|
|
};
|
|
|
|
|
2013-02-15 02:37:08 -06:00
|
|
|
(writer_factory, markdown_po)
|
2012-03-01 00:26:28 -06:00
|
|
|
}
|
|
|
|
|
2012-09-18 18:48:40 -05:00
|
|
|
fn future_writer() -> (Writer, future::Future<~str>) {
|
2013-02-02 05:10:12 -06:00
|
|
|
let (port, chan) = comm::stream();
|
2013-07-02 14:47:32 -05:00
|
|
|
let writer: ~fn(instr: WriteInstr) = |instr| chan.send(instr.clone());
|
2013-02-15 02:37:08 -06:00
|
|
|
let future = do future::from_fn || {
|
2012-07-14 00:57:48 -05:00
|
|
|
let mut res = ~"";
|
2012-03-09 18:11:56 -06:00
|
|
|
loop {
|
2012-08-28 08:43:58 -05:00
|
|
|
match port.recv() {
|
2013-06-11 21:13:42 -05:00
|
|
|
Write(s) => res.push_str(s),
|
2012-09-18 18:48:40 -05:00
|
|
|
Done => break
|
2012-03-01 00:26:28 -06:00
|
|
|
}
|
2012-03-26 05:39:20 -05:00
|
|
|
}
|
|
|
|
res
|
2012-03-01 00:26:28 -06:00
|
|
|
};
|
2013-02-15 02:37:08 -06:00
|
|
|
(writer, future)
|
2012-03-01 00:26:28 -06:00
|
|
|
}
|
2013-04-15 10:09:55 -05:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
2013-05-22 21:59:22 -05:00
|
|
|
|
2013-04-15 10:09:55 -05:00
|
|
|
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| {
|
2013-07-02 14:47:32 -05:00
|
|
|
let doc = extract::from_srv(srv.clone(), name.clone());
|
2013-04-15 10:09:55 -05:00
|
|
|
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());
|
2013-05-22 05:54:35 -05:00
|
|
|
let filename = make_local_filename(&config, page);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(filename.to_str(), ~"output/dir/test.md");
|
2013-04-15 10:09:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[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());
|
2013-05-22 05:54:35 -05:00
|
|
|
let filename = make_local_filename(&config, page);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(filename.to_str(), ~"output/dir/index.html");
|
2013-04-15 10:09:55 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[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 { } }");
|
2013-07-16 12:08:08 -05:00
|
|
|
// hidden __std_macros module at the start.
|
2013-07-02 14:47:32 -05:00
|
|
|
let modb = doc.cratemod().mods()[1].mods()[0].clone();
|
2013-04-15 10:09:55 -05:00
|
|
|
let page = doc::ItemPage(doc::ModTag(modb));
|
2013-05-22 05:54:35 -05:00
|
|
|
let filename = make_local_filename(&config, page);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(filename, Path("output/dir/a_b.html"));
|
2013-04-15 10:09:55 -05:00
|
|
|
}
|
|
|
|
}
|