use std::collections::HashMap; use regex::Regex; use core::Route; use plugin::{Plugin, PluginChain, TransformFileResult, FileChangeResult}; use rbx::{RbxInstance, RbxValue}; use vfs::VfsItem; lazy_static! { static ref SERVER_PATTERN: Regex = Regex::new(r"^(.*?)\.server\.lua$").unwrap(); static ref CLIENT_PATTERN: Regex = Regex::new(r"^(.*?)\.client\.lua$").unwrap(); static ref MODULE_PATTERN: Regex = Regex::new(r"^(.*?)\.lua$").unwrap(); } static SERVER_INIT: &'static str = "init.server.lua"; static CLIENT_INIT: &'static str = "init.client.lua"; static MODULE_INIT: &'static str = "init.lua"; pub struct ScriptPlugin; impl ScriptPlugin { pub fn new() -> ScriptPlugin { ScriptPlugin } } impl Plugin for ScriptPlugin { fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult { match vfs_item { &VfsItem::File { ref contents, .. } => { let name = vfs_item.name(); let (class_name, rbx_name) = { if let Some(captures) = SERVER_PATTERN.captures(name) { ("Script".to_string(), captures.get(1).unwrap().as_str().to_string()) } else if let Some(captures) = CLIENT_PATTERN.captures(name) { ("LocalScript".to_string(), captures.get(1).unwrap().as_str().to_string()) } else if let Some(captures) = MODULE_PATTERN.captures(name) { ("ModuleScript".to_string(), captures.get(1).unwrap().as_str().to_string()) } else { return TransformFileResult::Pass; } }; let mut properties = HashMap::new(); properties.insert("Source".to_string(), RbxValue::String { value: contents.clone(), }); TransformFileResult::Value(Some(RbxInstance { name: rbx_name, class_name: class_name, children: Vec::new(), properties, route: Some(vfs_item.route().to_vec()), })) }, &VfsItem::Dir { ref children, .. } => { let init_item = { let maybe_item = children.get(SERVER_INIT) .or(children.get(CLIENT_INIT)) .or(children.get(MODULE_INIT)); match maybe_item { Some(v) => v, None => return TransformFileResult::Pass, } }; let mut rbx_item = match self.transform_file(plugins, init_item) { TransformFileResult::Value(Some(item)) => item, _ => { eprintln!("Inconsistency detected in ScriptPlugin!"); return TransformFileResult::Pass; }, }; rbx_item.name.clear(); rbx_item.name.push_str(vfs_item.name()); for (child_name, child_item) in children { if child_name == init_item.name() { continue; } match plugins.transform_file(child_item) { Some(child_rbx_item) => { rbx_item.children.push(child_rbx_item); }, _ => {}, } } TransformFileResult::Value(Some(rbx_item)) }, } } fn handle_file_change(&self, route: &Route) -> FileChangeResult { let leaf = match route.last() { Some(v) => v, None => return FileChangeResult::Pass, }; let is_init = leaf == SERVER_INIT || leaf == CLIENT_INIT || leaf == MODULE_INIT; if is_init { let mut changed = route.clone(); changed.pop(); FileChangeResult::MarkChanged(Some(vec![changed])) } else { FileChangeResult::Pass } } }