use super::config::Config;
use super::es;
use es::traits::*;
use std::fs;
use std::process;
use util::append_indented;
pub struct Example<'a,'b> where 'b: 'a {
config: &'a Config<'b>,
code: String,
example: String,
before: String,
after: String,
}
const ALLOW: &[&str] = &["unused_variables", "unused_assignments", "unused_mut",
"unused_attributes", "dead_code", "unreachable_code"];
impl <'a,'b> Example<'a,'b> {
pub fn new (config: &'a Config<'b>, code: &str) -> Example<'a,'b> {
let mut template = String::new();
let mut before = String::new();
let mut after = String::new();
let mut iter = code.lines();
let mut code = String::new();
while let Some(line) = iter.next() {
if line.starts_with("#![") {
template += line;
template.push('\n');
} else {
code += line;
code.push('\n');
}
}
for lint in ALLOW.iter() {
template += &format!("#![allow({})]\n",lint);
}
if code.find("extern crate").is_none() {
template += &format!("extern crate {};\n",config.crate_name);
}
if ! config.question {
template += "fn main() {\n";
template += &code;
template += "}\n";
} else {
before += "fn run() -> std::result::Result<(),Box<std::error::Error>> {\n";
template += &before;
template += &code;
after += "Ok(())\n}\n\nfn main() {\n run().unwrap();\n}";
template += &after;
}
Example{
config: config,
code: code.into(),
example: template,
before: before,
after: after,
}
}
pub fn format(&self) -> String {
let comment = self.config.comment.as_str();
let attrib = if self.config.no_run {"rust,no_run"} else {""};
let start_guard = format!("{} ```{}\n", comment, attrib);
let end_guard = format!("{} ```\n", comment);
let hide = format!("{} #", comment);
let mut snippet = String::new();
snippet.push_str(&start_guard);
append_indented(&mut snippet,&self.before,&hide);
append_indented(&mut snippet,&self.code,comment);
append_indented(&mut snippet,&self.after,&hide);
snippet.push_str(&end_guard);
snippet
}
pub fn run(&self) -> (bool,String) {
if self.example.len() == 0 {
self.config.args.quit("please call massage() before run()");
}
if ! self.config.examples.is_dir() {
fs::create_dir(&self.config.examples).or_die("cannot create examples directory");
}
let test_file = self.config.examples.join(&self.config.file);
es::write_all(&test_file,&self.example);
let output = process::Command::new("cargo")
.arg(if self.config.no_run {"build"} else {"run"})
.arg("-q")
.arg("--color").arg("always") .arg("--example")
.arg(self.config.file.with_extension(""))
.output().or_die("could not run cargo");
let errors = String::from_utf8_lossy(&output.stderr);
if errors.len() > 0 {
eprintln!("{}", errors);
}
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
fs::remove_file(&test_file).or_die("can't remove temporary file in examples");
(output.status.success(), stdout)
}
}