extern crate getopts; extern crate pencil; extern crate modelthing; extern crate env_logger; extern crate markdown; #[macro_use] extern crate log; use std::env; use std::collections::BTreeMap; use std::process::exit; use std::path::Path; use getopts::Options; use pencil::Pencil; use pencil::{Request, PencilResult, Response, HTTPError, PencilError}; fn home(r: &mut Request) -> PencilResult { let context: BTreeMap = BTreeMap::new(); return r.app.render_template("home.html", &context); } fn readme(r: &mut Request) -> PencilResult { let mut context = BTreeMap::new(); let raw_text = include_str!("../../README.txt"); context.insert("raw_text".to_string(), raw_text.to_string()); return r.app.render_template("raw.html", &context); } fn model_list(r: &mut Request) -> PencilResult { let paths = modelthing::search_models(Path::new("examples")); let l: Vec = paths.iter().map(|x| Path::new(x).strip_prefix("examples").unwrap().to_string_lossy().to_string()).collect(); let mut context = BTreeMap::new(); context.insert("model_slug_list".to_string(), l); return r.app.render_template("model_list.html", &context); } fn model_view(r: &mut Request) -> PencilResult { let model_slug = r.view_args.get("model_slug").unwrap(); let model_path = Path::new("examples").join(model_slug); match modelthing::load_model_entry(model_path.as_path()) { Ok(me) => { let mut context = BTreeMap::new(); context.insert("model_slug".to_string(), model_slug.to_string()); context.insert("model_name".to_string(), me.ast.name.clone()); context.insert("model_description".to_string(), me.ast.description.clone().unwrap_or("".to_string())); context.insert("markdown_html".to_string(), markdown::to_html(&me.markdown)); context.insert("markdown".to_string(), me.markdown); context.insert("modelica".to_string(), format!("{:?}", me.ast)); r.app.render_template("model_view.html", &context) }, Err(_) => Err(PencilError::PenHTTPError(pencil::HTTPError::NotFound)), } } fn page_not_found(_: HTTPError) -> PencilResult { let mut response = Response::from("404: Not Found"); response.status_code = 404; Ok(response) } fn server_error(_: HTTPError) -> PencilResult { let mut response = Response::from("500: Server Error"); response.status_code = 500; Ok(response) } fn print_usage(opts: Options) { let brief = "usage:\tmt-webface [options]"; println!(""); print!("{}", opts.usage(&brief)); } fn main() { let args: Vec = env::args().collect(); let mut opts = Options::new(); opts.optflag("h", "help", "print this help menu"); opts.optflag("b", "bind", "local IP:port to bind to"); opts.optflag("", "version", "print the version"); let matches = match opts.parse(&args[1..]) { Ok(m) => m, Err(f) => { println!("{}\n", f.to_string()); print_usage(opts); exit(-1); } }; if matches.opt_present("help") { print_usage(opts); return; } if matches.opt_present("version") { println!("modelthing {}", env!("CARGO_PKG_VERSION")); return; } env_logger::init().unwrap(); let mut app = Pencil::new("webface"); app.name = "modelthing-webface".to_string(); app.set_debug(true); app.set_log_level(); app.httperrorhandler(404, page_not_found); app.httperrorhandler(500, server_error); app.enable_static_file_handling(); debug!("root_path: {}", app.root_path); app.register_template("base.html"); app.register_template("home.html"); app.register_template("raw.html"); app.get("/", "home", home); app.get("/readme/", "readme", readme); app.register_template("model_list.html"); app.get("/model_list/", "model_list", model_list); app.register_template("model_view.html"); app.get("/model//", "model", model_view); let bind = matches.opt_str("bind").unwrap_or("127.0.0.1:5000".to_string()); let bind_str: &str = &bind; info!("Running on {}", bind); app.run(bind_str); }